aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
commit51fb8b013e7734b795139f49d3b1f77c539be20a (patch)
tree59e0e47a9831dcf0e21e547927c8ebb7e113bfd1
parent73490b890977362d28dd6326843a1ecae413921d (diff)
downloadsrc-51fb8b013e7734b795139f49d3b1f77c539be20a.tar.gz
src-51fb8b013e7734b795139f49d3b1f77c539be20a.zip
Update clang to r86025.vendor/clang/clang-r86025
Notes
Notes: svn path=/vendor/clang/dist/; revision=198893 svn path=/vendor/clang/clang-r86025/; revision=198895; tag=vendor/clang/clang-r86025
-rw-r--r--CMakeLists.txt10
-rw-r--r--clang.xcodeproj/project.pbxproj18
-rw-r--r--docs/LanguageExtensions.html64
-rw-r--r--docs/tools/clang.pod4
-rw-r--r--include/clang-c/Index.h97
-rw-r--r--include/clang/AST/ASTContext.h74
-rw-r--r--include/clang/AST/CanonicalType.h19
-rw-r--r--include/clang/AST/Decl.h91
-rw-r--r--include/clang/AST/DeclGroup.h2
-rw-r--r--include/clang/AST/DeclNodes.def1
-rw-r--r--include/clang/AST/DeclObjC.h14
-rw-r--r--include/clang/AST/DeclTemplate.h380
-rw-r--r--include/clang/AST/Expr.h272
-rw-r--r--include/clang/AST/ExprCXX.h58
-rw-r--r--include/clang/AST/RecordLayout.h2
-rw-r--r--include/clang/AST/Redeclarable.h5
-rw-r--r--include/clang/AST/StmtIterator.h2
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/AST/TemplateBase.h366
-rw-r--r--include/clang/AST/TemplateName.h81
-rw-r--r--include/clang/AST/Type.h8
-rw-r--r--include/clang/AST/TypeLoc.h135
-rw-r--r--include/clang/Analysis/CallGraph.h3
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h13
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h33
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h86
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h38
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h28
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h30
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h53
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h28
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h34
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h32
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h39
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h85
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h19
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h5
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h7
-rw-r--r--include/clang/Analysis/PathSensitive/SymbolManager.h2
-rw-r--r--include/clang/Analysis/ProgramPoint.h2
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h2
-rw-r--r--include/clang/Basic/Builtins.def2
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td13
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td44
-rw-r--r--include/clang/Basic/OnDiskHashTable.h2
-rw-r--r--include/clang/Basic/OperatorKinds.h5
-rw-r--r--include/clang/Basic/PartialDiagnostic.h18
-rw-r--r--include/clang/Basic/SourceManager.h2
-rw-r--r--include/clang/Basic/TargetInfo.h6
-rw-r--r--include/clang/Driver/Options.def4
-rw-r--r--include/clang/Frontend/ASTUnit.h10
-rw-r--r--include/clang/Frontend/CompileOptions.h4
-rw-r--r--include/clang/Frontend/DeclXML.def4
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h49
-rw-r--r--include/clang/Frontend/InitHeaderSearch.h10
-rw-r--r--include/clang/Frontend/InitPreprocessor.h3
-rw-r--r--include/clang/Frontend/PCHBitCodes.h4
-rw-r--r--include/clang/Frontend/PCHReader.h9
-rw-r--r--include/clang/Frontend/PCHWriter.h4
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h31
-rw-r--r--include/clang/Index/Utils.h3
-rw-r--r--include/clang/Lex/LiteralSupport.h2
-rw-r--r--include/clang/Lex/Preprocessor.h68
-rw-r--r--include/clang/Lex/Token.h8
-rw-r--r--include/clang/Parse/Action.h323
-rw-r--r--include/clang/Parse/DeclSpec.h363
-rw-r--r--include/clang/Parse/Parser.h142
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h13
-rw-r--r--lib/AST/ASTContext.cpp223
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Decl.cpp125
-rw-r--r--lib/AST/DeclBase.cpp1
-rw-r--r--lib/AST/DeclCXX.cpp39
-rw-r--r--lib/AST/DeclObjC.cpp27
-rw-r--r--lib/AST/DeclPrinter.cpp9
-rw-r--r--lib/AST/DeclTemplate.cpp72
-rw-r--r--lib/AST/Expr.cpp201
-rw-r--r--lib/AST/ExprCXX.cpp26
-rw-r--r--lib/AST/ExprConstant.cpp141
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp14
-rw-r--r--lib/AST/RecordLayoutBuilder.h2
-rw-r--r--lib/AST/StmtPrinter.cpp14
-rw-r--r--lib/AST/StmtProfile.cpp77
-rw-r--r--lib/AST/TemplateBase.cpp97
-rw-r--r--lib/AST/TemplateName.cpp9
-rw-r--r--lib/AST/Type.cpp161
-rw-r--r--lib/Analysis/AttrNonNullChecker.cpp100
-rw-r--r--lib/Analysis/BadCallChecker.cpp44
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp1
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.h1
-rw-r--r--lib/Analysis/BasicStore.cpp26
-rw-r--r--lib/Analysis/CFRefCount.cpp34
-rw-r--r--lib/Analysis/CMakeLists.txt10
-rw-r--r--lib/Analysis/CallGraph.cpp4
-rw-r--r--lib/Analysis/CheckObjCUnusedIVars.cpp35
-rw-r--r--lib/Analysis/DereferenceChecker.cpp112
-rw-r--r--lib/Analysis/DivZeroChecker.cpp70
-rw-r--r--lib/Analysis/GRExprEngine.cpp391
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp390
-rw-r--r--lib/Analysis/NSAutoreleasePoolChecker.cpp84
-rw-r--r--lib/Analysis/NSErrorChecker.cpp (renamed from lib/Analysis/CheckNSError.cpp)31
-rw-r--r--lib/Analysis/RegionStore.cpp39
-rw-r--r--lib/Analysis/UndefinedArgChecker.cpp43
-rw-r--r--lib/Analysis/UndefinedAssignmentChecker.cpp61
-rw-r--r--lib/Analysis/VLASizeChecker.cpp102
-rw-r--r--lib/Basic/CMakeLists.txt2
-rw-r--r--lib/Basic/IdentifierTable.cpp14
-rw-r--r--lib/Basic/TargetInfo.cpp4
-rw-r--r--lib/Basic/Targets.cpp2
-rw-r--r--lib/CodeGen/CGBuiltin.cpp13
-rw-r--r--lib/CodeGen/CGCXX.cpp172
-rw-r--r--lib/CodeGen/CGCall.cpp2
-rw-r--r--lib/CodeGen/CGDecl.cpp44
-rw-r--r--lib/CodeGen/CGException.cpp105
-rw-r--r--lib/CodeGen/CGExpr.cpp224
-rw-r--r--lib/CodeGen/CGExprAgg.cpp5
-rw-r--r--lib/CodeGen/CGExprConstant.cpp17
-rw-r--r--lib/CodeGen/CGExprScalar.cpp33
-rw-r--r--lib/CodeGen/CGObjC.cpp22
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.h2
-rw-r--r--lib/CodeGen/CGRtti.cpp21
-rw-r--r--lib/CodeGen/CGStmt.cpp5
-rw-r--r--lib/CodeGen/CGValue.h2
-rw-r--r--lib/CodeGen/CGVtable.cpp228
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp75
-rw-r--r--lib/CodeGen/CodeGenFunction.h27
-rw-r--r--lib/CodeGen/CodeGenModule.cpp36
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/Mangle.cpp21
-rw-r--r--lib/CodeGen/Mangle.h4
-rw-r--r--lib/Driver/Tools.cpp217
-rw-r--r--lib/Driver/Types.cpp82
-rw-r--r--lib/Frontend/ASTConsumers.cpp7
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp1
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp312
-rw-r--r--lib/Frontend/InitPreprocessor.cpp33
-rw-r--r--lib/Frontend/PCHReader.cpp28
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp20
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp4
-rw-r--r--lib/Frontend/PCHWriter.cpp24
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp12
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp4
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp6
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp55
-rw-r--r--lib/Headers/CMakeLists.txt2
-rw-r--r--lib/Headers/stdint.h3
-rw-r--r--lib/Index/ResolveLocation.cpp79
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp14
-rw-r--r--lib/Lex/PPExpressions.cpp118
-rw-r--r--lib/Lex/PPMacroExpansion.cpp131
-rw-r--r--lib/Parse/AttributeList.cpp145
-rw-r--r--lib/Parse/DeclSpec.cpp25
-rw-r--r--lib/Parse/MinimalAction.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp359
-rw-r--r--lib/Parse/ParseDeclCXX.cpp60
-rw-r--r--lib/Parse/ParseExpr.cpp168
-rw-r--r--lib/Parse/ParseExprCXX.cpp623
-rw-r--r--lib/Parse/ParseObjc.cpp146
-rw-r--r--lib/Parse/ParseStmt.cpp3
-rw-r--r--lib/Parse/ParseTemplate.cpp32
-rw-r--r--lib/Parse/Parser.cpp84
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp11
-rw-r--r--lib/Sema/Sema.cpp40
-rw-r--r--lib/Sema/Sema.h217
-rw-r--r--lib/Sema/SemaCXXCast.cpp8
-rw-r--r--lib/Sema/SemaChecking.cpp10
-rw-r--r--lib/Sema/SemaCodeComplete.cpp95
-rw-r--r--lib/Sema/SemaDecl.cpp261
-rw-r--r--lib/Sema/SemaDeclAttr.cpp100
-rw-r--r--lib/Sema/SemaDeclCXX.cpp114
-rw-r--r--lib/Sema/SemaDeclObjC.cpp70
-rw-r--r--lib/Sema/SemaExpr.cpp490
-rw-r--r--lib/Sema/SemaExprCXX.cpp186
-rw-r--r--lib/Sema/SemaLookup.cpp22
-rw-r--r--lib/Sema/SemaOverload.cpp244
-rw-r--r--lib/Sema/SemaStmt.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp439
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp161
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp381
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp395
-rw-r--r--lib/Sema/SemaType.cpp265
-rw-r--r--lib/Sema/TreeTransform.h896
-rw-r--r--test/Analysis/misc-ps-eager-assume.m43
-rw-r--r--test/Analysis/misc-ps-region-store.m59
-rw-r--r--test/Analysis/misc-ps.m10
-rw-r--r--test/Analysis/outofbound.c2
-rw-r--r--test/Analysis/retain-release-gc-only.m11
-rw-r--r--test/Analysis/retain-release.m26
-rw-r--r--test/Analysis/uninit-vals-ps-region.c15
-rw-r--r--test/Analysis/unused-ivars.m22
-rw-r--r--test/CMakeLists.txt14
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp2
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp2
-rw-r--r--test/CXX/class/class.union/p1.cpp9
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp2
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp145
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/p6.cpp39
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p5.cpp2
-rw-r--r--test/CXX/temp/temp.param/p14.cpp2
-rw-r--r--test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp2
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp3
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p10.cpp33
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p12.cpp6
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p3.cpp14
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p5.cpp17
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p6.cpp14
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p7.cpp36
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p8.cpp27
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp66
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p9.cpp59
-rw-r--r--test/CodeCompletion/macros.c37
-rw-r--r--test/CodeGen/2008-07-21-mixed-var-fn-decl.c5
-rw-r--r--test/CodeGen/2008-07-29-override-alias-decl.c15
-rw-r--r--test/CodeGen/asm-inout.c2
-rw-r--r--test/CodeGen/blocks-2.c2
-rw-r--r--test/CodeGen/builtin-unwind-init.c5
-rw-r--r--test/CodeGen/cast-to-union.c2
-rw-r--r--test/CodeGen/function-attributes.c56
-rw-r--r--test/CodeGen/indirect-goto.c23
-rw-r--r--test/CodeGen/mangle.c23
-rw-r--r--test/CodeGen/object-size.c126
-rw-r--r--test/CodeGen/union-init2.c2
-rw-r--r--test/CodeGen/volatile.c10
-rw-r--r--test/CodeGenCXX/array-construction.cpp40
-rw-r--r--test/CodeGenCXX/ptr-to-datamember.cpp16
-rw-r--r--test/CodeGenCXX/ptr-to-member-function.cpp53
-rw-r--r--test/CodeGenCXX/temporaries.cpp6
-rw-r--r--test/CodeGenCXX/virt.cpp208
-rw-r--r--test/CodeGenObjC/PR4894-recursive-debug-crash.m2
-rw-r--r--test/CodeGenObjC/encode-test-2.m3
-rw-r--r--test/CodeGenObjC/synthesize_ivar.m15
-rw-r--r--test/Coverage/objc-language-features.inc6
-rw-r--r--test/Coverage/targets.c4
-rw-r--r--test/Driver/analyze.c8
-rw-r--r--test/Driver/ccc-add-args.c6
-rw-r--r--test/Driver/hello.c4
-rw-r--r--test/Driver/phases.c126
-rw-r--r--test/Driver/qa_override.c12
-rw-r--r--test/Driver/std.c12
-rw-r--r--test/FixIt/fixit-pmem.cpp23
-rw-r--r--test/Frontend/darwin-version.c20
-rw-r--r--test/Frontend/dependency-gen.c9
-rw-r--r--test/Lexer/block_cmt_end.c4
-rw-r--r--test/Makefile3
-rw-r--r--test/Misc/message-length.c2
-rw-r--r--test/PCH/pr4489.c5
-rw-r--r--test/Parser/cxx-parse-member-pointer-op.cpp13
-rw-r--r--test/Parser/cxx-template-decl.cpp6
-rw-r--r--test/Preprocessor/assembler-with-cpp.c34
-rw-r--r--test/Preprocessor/c99-6_10_3_3_p4.c6
-rw-r--r--test/Preprocessor/c99-6_10_3_4_p5.c11
-rw-r--r--test/Preprocessor/c99-6_10_3_4_p6.c13
-rw-r--r--test/Preprocessor/c99-6_10_3_4_p7.c5
-rw-r--r--test/Preprocessor/c99-6_10_3_4_p9.c20
-rw-r--r--test/Preprocessor/comment_save.c7
-rw-r--r--test/Preprocessor/comment_save_macro.c11
-rw-r--r--test/Preprocessor/has_include.c83
-rw-r--r--test/Preprocessor/init.c945
-rw-r--r--test/Preprocessor/line-directive.c2
-rw-r--r--test/Preprocessor/macro_disable3.c4
-rw-r--r--test/Preprocessor/macro_paste_mscomment.c10
-rw-r--r--test/Preprocessor/macro_rescan_varargs.c7
-rw-r--r--test/Preprocessor/macro_rparen_scan2.c4
-rw-r--r--test/Preprocessor/macro_undef.c4
-rw-r--r--test/Preprocessor/output_paste_avoid.c17
-rw-r--r--test/Preprocessor/stdint.c1244
-rw-r--r--test/Preprocessor/stringize_misc.c16
-rw-r--r--test/Sema/attr-deprecated.c57
-rw-r--r--test/Sema/callingconv.c9
-rw-r--r--test/Sema/constant-builtins-2.c2
-rw-r--r--test/Sema/decl-invalid.c3
-rw-r--r--test/Sema/format-strings.c6
-rw-r--r--test/Sema/init.c2
-rw-r--r--test/Sema/offsetof.c6
-rw-r--r--test/Sema/parentheses.c20
-rw-r--r--test/Sema/return-noreturn.c8
-rw-r--r--test/Sema/return.c4
-rw-r--r--test/Sema/statements.c6
-rw-r--r--test/Sema/stdcall-fastcall.c4
-rw-r--r--test/Sema/vector-init.c4
-rw-r--r--test/SemaCXX/constructor.cpp2
-rw-r--r--test/SemaCXX/implicit-int.cpp2
-rw-r--r--test/SemaCXX/invalid-member-expr.cpp8
-rw-r--r--test/SemaCXX/invalid-template-specifier.cpp2
-rw-r--r--test/SemaCXX/nested-name-spec.cpp2
-rw-r--r--test/SemaCXX/new-delete.cpp1
-rw-r--r--test/SemaCXX/overloaded-operator.cpp28
-rw-r--r--test/SemaCXX/ptrtomember-badcall.cpp13
-rw-r--r--test/SemaCXX/typedef-redecl.cpp2
-rw-r--r--test/SemaCXX/value-initialization.cpp10
-rw-r--r--test/SemaObjC/conditional-expr-6.m51
-rw-r--r--test/SemaObjC/continuation-class-err.m33
-rw-r--r--test/SemaObjC/id-isa-ref.m2
-rw-r--r--test/SemaObjC/property-category-4.m18
-rw-r--r--test/SemaObjC/return.m18
-rw-r--r--test/SemaObjCXX/overload.mm2
-rw-r--r--test/SemaObjCXX/references.mm2
-rw-r--r--test/SemaTemplate/class-template-spec.cpp12
-rw-r--r--test/SemaTemplate/constructor-template.cpp1
-rw-r--r--test/SemaTemplate/copy-ctor-assign.cpp18
-rw-r--r--test/SemaTemplate/default-expr-arguments.cpp24
-rw-r--r--test/SemaTemplate/ext-vector-type.cpp13
-rw-r--r--test/SemaTemplate/friend-template.cpp29
-rw-r--r--test/SemaTemplate/instantiate-cast.cpp12
-rw-r--r--test/SemaTemplate/instantiate-declref-ice.cpp30
-rw-r--r--test/SemaTemplate/instantiate-declref.cpp18
-rw-r--r--test/SemaTemplate/instantiate-function-1.mm2
-rw-r--r--test/SemaTemplate/instantiate-method.cpp17
-rw-r--r--test/SemaTemplate/instantiate-non-type-template-parameter.cpp14
-rw-r--r--test/SemaTemplate/instantiate-subscript.cpp17
-rw-r--r--test/SemaTemplate/member-template-access-expr.cpp45
-rw-r--r--test/SemaTemplate/nested-name-spec-template.cpp2
-rw-r--r--test/SemaTemplate/nested-template.cpp7
-rw-r--r--test/SemaTemplate/operator-function-id-template.cpp28
-rw-r--r--test/SemaTemplate/template-id-expr.cpp14
-rw-r--r--test/SemaTemplate/template-id-printing.cpp13
-rw-r--r--test/lit.site.cfg.in1
-rw-r--r--tools/CIndex/CIndex.cpp106
-rw-r--r--tools/CIndex/CIndex.exports32
-rw-r--r--tools/CIndex/CMakeLists.txt1
-rw-r--r--tools/CMakeLists.txt5
-rw-r--r--tools/c-index-test/c-index-test.c24
-rw-r--r--tools/clang-cc/clang-cc.cpp263
-rw-r--r--tools/wpa/clang-wpa.cpp4
-rw-r--r--www/UniversalDriver.html3
-rw-r--r--www/analyzer/latest_checker.html.incl2
-rw-r--r--www/cxx_status.html20
338 files changed, 14006 insertions, 5659 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0cd52d0d946b..7f4ab33b33a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,7 +65,7 @@ macro(add_clang_library name)
set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag})
endif(MSVC)
install(TARGETS ${name}
- LIBRARY DESTINATION lib
+ LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
endmacro(add_clang_library)
@@ -83,8 +83,12 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}/include
)
-install(DIRECTORY include
- DESTINATION .
+install(DIRECTORY include/
+ DESTINATION include
+ FILES_MATCHING
+ PATTERN "*.def"
+ PATTERN "*.h"
+ PATTERN "*.td"
PATTERN ".svn" EXCLUDE
)
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index 24e1ac360f72..2b4aa04ca33c 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -49,6 +49,7 @@
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */; };
+ 1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
@@ -399,6 +400,7 @@
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
+ 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
@@ -515,6 +517,13 @@
9012911C1048068D0083456D /* ASTUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTUnit.cpp; path = lib/Frontend/ASTUnit.cpp; sourceTree = "<group>"; };
9012911F104812F90083456D /* CIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndex.cpp; path = tools/CIndex/CIndex.cpp; sourceTree = "<group>"; };
90129120104812F90083456D /* CIndex.exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CIndex.exports; path = tools/CIndex/CIndex.exports; sourceTree = "<group>"; };
+ 904753791096376F00CBDDDD /* CXXInheritance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXXInheritance.h; path = clang/AST/CXXInheritance.h; sourceTree = "<group>"; };
+ 9047537A1096376F00CBDDDD /* Redeclarable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Redeclarable.h; path = clang/AST/Redeclarable.h; sourceTree = "<group>"; };
+ 9047537B1096376F00CBDDDD /* TypeLoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLoc.h; path = clang/AST/TypeLoc.h; sourceTree = "<group>"; };
+ 9047537C1096376F00CBDDDD /* TypeLocBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLocBuilder.h; path = clang/AST/TypeLocBuilder.h; sourceTree = "<group>"; };
+ 9047537D1096376F00CBDDDD /* TypeLocNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeLocNodes.def; path = clang/AST/TypeLocNodes.def; sourceTree = "<group>"; };
+ 9047537E1096376F00CBDDDD /* TypeLocVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLocVisitor.h; path = clang/AST/TypeLocVisitor.h; sourceTree = "<group>"; };
+ 9047537F1096376F00CBDDDD /* TypeVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeVisitor.h; path = clang/AST/TypeVisitor.h; sourceTree = "<group>"; };
9063F2210F9E8BDF002F7251 /* ExternalSemaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalSemaSource.h; path = clang/Sema/ExternalSemaSource.h; sourceTree = "<group>"; };
9063F2220F9E8BDF002F7251 /* SemaConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaConsumer.h; path = clang/Sema/SemaConsumer.h; sourceTree = "<group>"; };
9063F2280F9E911F002F7251 /* OnDiskHashTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnDiskHashTable.h; sourceTree = "<group>"; };
@@ -1257,6 +1266,7 @@
35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */,
35A3E7010DD3874400757F74 /* CGDebugInfo.h */,
DE4264FB0C113592005A861D /* CGDecl.cpp */,
+ 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */,
DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */,
DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */,
DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */,
@@ -1298,6 +1308,13 @@
DEC8D98B0A9433BC00353FCA /* AST */ = {
isa = PBXGroup;
children = (
+ 904753791096376F00CBDDDD /* CXXInheritance.h */,
+ 9047537A1096376F00CBDDDD /* Redeclarable.h */,
+ 9047537B1096376F00CBDDDD /* TypeLoc.h */,
+ 9047537C1096376F00CBDDDD /* TypeLocBuilder.h */,
+ 9047537D1096376F00CBDDDD /* TypeLocNodes.def */,
+ 9047537E1096376F00CBDDDD /* TypeLocVisitor.h */,
+ 9047537F1096376F00CBDDDD /* TypeVisitor.h */,
DECB78540FA58F5500F5FBC7 /* AccessSpecifier.h */,
DE613EF30E0E148D00B05B79 /* APValue.h */,
DEC8D9A30A94346E00353FCA /* AST.h */,
@@ -1901,6 +1918,7 @@
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */,
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,
+ 1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 9ac35e1dc2dc..1c892fd23a5a 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -20,6 +20,7 @@ td {
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#feature_check">Feature Checking Macros</a></li>
+<li><a href="#has_include">Include File 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>
@@ -112,6 +113,69 @@ can be used like this:</p>
<p>The feature tag is described along with the language feature below.</p>
+<!-- ======================================================================= -->
+<h2 id="has_include">Include File Checking Macros</h2>
+<!-- ======================================================================= -->
+
+<p>Not all developments systems have the same include files.
+The <a href="#__has_include">__has_include</a> and
+<a href="#__has_include_next">__has_include_next</a> macros allow you to
+check for the existence of an include file before doing
+a possibly failing #include directive.</p>
+
+<!-- ======================================================================= -->
+<h3 id="__has_include">__has_include</h3>
+<!-- ======================================================================= -->
+
+<p>This function-like macro takes a single file name string argument that
+is the name of an include file. It evaluates to 1 if the file can
+be found using the include paths, or 0 otherwise:</p>
+
+<blockquote>
+<pre>
+// Note the two possible file name string formats.
+#if __has_include("myinclude.h") && __has_include(&lt;stdint.h&gt;)
+# include "myinclude.h"
+#endif
+
+// To avoid problem with non-clang compilers not having this macro.
+#if defined(__has_include) && __has_include("myinclude.h")
+# include "myinclude.h"
+#endif
+</pre>
+</blockquote>
+
+<p>To test for this feature, use #if defined(__has_include).</p>
+
+<!-- ======================================================================= -->
+<h3 id="__has_include_next">__has_include_next</h3>
+<!-- ======================================================================= -->
+
+<p>This function-like macro takes a single file name string argument that
+is the name of an include file. It is like __has_include except that it
+looks for the second instance of the given file found in the include
+paths. It evaluates to 1 if the second instance of the file can
+be found using the include paths, or 0 otherwise:</p>
+
+<blockquote>
+<pre>
+// Note the two possible file name string formats.
+#if __has_include_next("myinclude.h") && __has_include_next(&lt;stdint.h&gt;)
+# include_next "myinclude.h"
+#endif
+
+// To avoid problem with non-clang compilers not having this macro.
+#if defined(__has_include_next) && __has_include_next("myinclude.h")
+# include_next "myinclude.h"
+#endif
+</pre>
+</blockquote>
+
+<p>Note that __has_include_next, like the GNU extension
+#include_next directive, is intended for use in headers only,
+and will issue a warning if used in the top-level compilation
+file. A warning will also be issued if an absolute path
+is used in the file argument.</p>
<!-- ======================================================================= -->
<h2 id="builtinmacros">Builtin Macros</h2>
diff --git a/docs/tools/clang.pod b/docs/tools/clang.pod
index daa738798930..42cf8fa2d711 100644
--- a/docs/tools/clang.pod
+++ b/docs/tools/clang.pod
@@ -424,6 +424,10 @@ Add the specified directory to the search path for framework include files.
Do not search the standard system directories for include files.
+=item B<-nobuiltininc>
+
+Do not search clang's builtin directory for include files.
+
=cut
## TODO, but do we really want people using this stuff?
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 44cbe0efff81..1a58f44ff4c2 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -16,10 +16,23 @@
#ifndef CLANG_C_INDEX_H
#define CLANG_C_INDEX_H
+#include <sys/stat.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+/* MSVC DLL import/export. */
+#ifdef _MSC_VER
+ #ifdef _CINDEX_LIB_
+ #define CINDEX_LINKAGE __declspec(dllexport)
+ #else
+ #define CINDEX_LINKAGE __declspec(dllimport)
+ #endif
+#else
+ #define CINDEX_LINKAGE
+#endif
+
/*
Clang indeX abstractions. The backing store for the following API's will be
clangs AST file (currently based on PCH). AST files are created as follows:
@@ -33,6 +46,7 @@ typedef void *CXIndex; /* An indexing instance. */
typedef void *CXTranslationUnit; /* A translation unit instance. */
+typedef void *CXFile; /* A source file */
typedef void *CXDecl; /* A specific declaration within a translation unit. */
typedef void *CXStmt; /* A specific statement within a function/method */
@@ -138,22 +152,22 @@ typedef void *CXEntity;
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
* (which gives the indexer the same performance benefit as the compiler).
*/
-CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics);
-void clang_disposeIndex(CXIndex);
+CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
-const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/*
* \brief Create a translation unit from an AST file (-emit-ast).
*/
-CXTranslationUnit clang_createTranslationUnit(
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
CXIndex, const char *ast_filename
);
/**
* \brief Destroy the specified CXTranslationUnit object.
*/
-void clang_disposeTranslationUnit(CXTranslationUnit);
+CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
* \brief Return the CXTranslationUnit for a given source file and the provided
@@ -170,7 +184,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit);
* '-o <output file>' (both '-o' and '<output file>' are ignored)
*
*/
-CXTranslationUnit clang_createTranslationUnitFromSourceFile(
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CXIndex CIdx,
const char *source_filename /* specify NULL if the source file is in clang_command_line_args */,
int num_clang_command_line_args,
@@ -197,7 +211,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
typedef void *CXClientData;
typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor,
CXClientData);
-void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
+CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
CXClientData);
/*
@@ -227,23 +241,30 @@ void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
*/
typedef void (*CXDeclIterator)(CXDecl, CXCursor, CXClientData);
-void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
+CINDEX_LINKAGE void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
+
+/*
+ * CXFile Operations.
+ */
+CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
+CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/*
* CXEntity Operations.
*/
-const char *clang_getDeclarationName(CXEntity);
-const char *clang_getURI(CXEntity);
-CXEntity clang_getEntity(const char *URI);
+CINDEX_LINKAGE const char *clang_getDeclarationName(CXEntity);
+CINDEX_LINKAGE const char *clang_getURI(CXEntity);
+CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
/*
* CXDecl Operations.
*/
-CXCursor clang_getCursorFromDecl(CXDecl);
-CXEntity clang_getEntityFromDecl(CXDecl);
-const char *clang_getDeclSpelling(CXDecl);
-unsigned clang_getDeclLine(CXDecl);
-unsigned clang_getDeclColumn(CXDecl);
-const char *clang_getDeclSource(CXDecl);
+CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
+CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
+CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
+CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
+CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
+CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
+CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
/*
* CXCursor Operations.
@@ -252,38 +273,24 @@ const char *clang_getDeclSource(CXDecl);
Usage: clang_getCursor() will translate a source/line/column position
into an AST cursor (to derive semantic information from the source code).
*/
-CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
+CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
unsigned line, unsigned column);
-/**
- Usage: clang_getCursorWithHint() provides the same functionality as
- clang_getCursor() except that it takes an option 'hint' argument.
- The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by
- the caller) that should be initialized with clang_initCXLookupHint().
-
- FIXME: Add a better comment once getCursorWithHint() has more functionality.
- */
-typedef CXCursor CXLookupHint;
-CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,
- unsigned line, unsigned column,
- CXLookupHint *hint);
-
-void clang_initCXLookupHint(CXLookupHint *hint);
-
-enum CXCursorKind clang_getCursorKind(CXCursor);
-unsigned clang_isDeclaration(enum CXCursorKind);
-unsigned clang_isReference(enum CXCursorKind);
-unsigned clang_isDefinition(enum CXCursorKind);
-unsigned clang_isInvalid(enum CXCursorKind);
+CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
+CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
-unsigned clang_getCursorLine(CXCursor);
-unsigned clang_getCursorColumn(CXCursor);
-const char *clang_getCursorSource(CXCursor);
-const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
+CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
+CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
+CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
/* for debug/testing */
-const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
-void clang_getDefinitionSpellingAndExtent(CXCursor,
+CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
+CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
const char **startBuf,
const char **endBuf,
unsigned *startLine,
@@ -296,7 +303,7 @@ void clang_getDefinitionSpellingAndExtent(CXCursor,
* declaration.
* If CXCursorKind == Cursor_Declaration, then this will return the declaration.
*/
-CXDecl clang_getCursorDecl(CXCursor);
+CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
#ifdef __cplusplus
}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 30896c91a143..7392170be995 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -16,6 +16,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
@@ -301,22 +302,22 @@ public:
const char *getCommentForDecl(const Decl *D);
// Builtin Types.
- QualType VoidTy;
- QualType BoolTy;
- QualType CharTy;
- QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
- QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
- QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
- QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
- QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
- QualType UnsignedLongLongTy, UnsignedInt128Ty;
- QualType FloatTy, DoubleTy, LongDoubleTy;
- QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
- QualType VoidPtrTy, NullPtrTy;
- QualType OverloadTy;
- QualType DependentTy;
- QualType UndeducedAutoTy;
- QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
+ CanQualType VoidTy;
+ CanQualType BoolTy;
+ CanQualType CharTy;
+ CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
+ CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
+ CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
+ CanQualType FloatTy, DoubleTy, LongDoubleTy;
+ CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
+ CanQualType VoidPtrTy, NullPtrTy;
+ CanQualType OverloadTy;
+ CanQualType DependentTy;
+ CanQualType UndeducedAutoTy;
+ CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@@ -387,10 +388,16 @@ public:
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
+ CanQualType getComplexType(CanQualType T) {
+ return CanQualType::CreateUnsafe(getComplexType((QualType) T));
+ }
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T);
+ CanQualType getPointerType(CanQualType T) {
+ return CanQualType::CreateUnsafe(getPointerType((QualType) T));
+ }
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
@@ -525,6 +532,11 @@ public:
unsigned NumArgs,
QualType Canon = QualType());
+ QualType getTemplateSpecializationType(TemplateName T,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ QualType Canon = QualType());
+
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
QualType NamedType);
QualType getTypenameType(NestedNameSpecifier *NNS,
@@ -728,6 +740,8 @@ public:
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name);
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator);
enum GetBuiltinTypeError {
GE_None, //< No error
@@ -739,7 +753,7 @@ public:
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
private:
- QualType getFromTargetType(unsigned Type) const;
+ CanQualType getFromTargetType(unsigned Type) const;
//===--------------------------------------------------------------------===//
// Type Predicates.
@@ -826,6 +840,8 @@ public:
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
+ void CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols);
//===--------------------------------------------------------------------===//
// Type Operators
@@ -1013,7 +1029,9 @@ public:
bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS);
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
-
+ QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+
// Functions for calculating composite types
QualType mergeTypes(QualType, QualType);
QualType mergeFunctionTypes(QualType, QualType);
@@ -1085,12 +1103,18 @@ public:
/// should be calculated based on the type.
DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
+ /// \brief Allocate a DeclaratorInfo where all locations have been
+ /// initialized to a given location, which defaults to the empty
+ /// location.
+ DeclaratorInfo *
+ getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation());
+
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
void InitBuiltinTypes();
- void InitBuiltinType(QualType &R, BuiltinType::Kind K);
+ void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
// Return the ObjC type encoding for a given type.
void getObjCEncodingForTypeImpl(QualType t, std::string &S,
@@ -1103,6 +1127,18 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
};
+
+/// @brief Utility function for constructing a nullary selector.
+static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(0, &II);
+}
+
+/// @brief Utility function for constructing an unary selector.
+static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(1, &II);
+}
} // end namespace clang
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 8b84bc267997..a7750517090e 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -64,15 +64,6 @@ public:
CanQual(const CanQual<U>& Other,
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
- /// \brief Implicit conversion to the underlying pointer.
- ///
- /// Also provides the ability to use canonical types in a boolean context,
- /// e.g.,
- /// @code
- /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
- /// @endcode
- operator const T*() const { return getTypePtr(); }
-
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
@@ -80,6 +71,10 @@ public:
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
+ bool isNull() const {
+ return Stored.isNull();
+ }
+
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
@@ -125,8 +120,10 @@ public:
/// \brief Retrieve the unqualified form of this type.
CanQual<T> getUnqualifiedType() const;
- CanQual<T> getQualifiedType(unsigned TQs) const {
- return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs));
+ /// \brief Retrieves a version of this type with const applied.
+ /// Note that this does not always yield a canonical type.
+ QualType withConst() const {
+ return Stored.withConst();
}
/// \brief Determines whether this canonical type is more qualified than
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 72ce0d852cfc..813e83accdb1 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -605,6 +605,9 @@ public:
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a static data member.
bool isOutOfLine() const;
+
+ /// \brief If this is a static data member, find its out-of-line definition.
+ VarDecl *getOutOfLineDefinition();
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
@@ -768,7 +771,11 @@ public:
Init = (UnparsedDefaultArgument *)0;
}
- QualType getOriginalType() const;
+ QualType getOriginalType() const {
+ if (getDeclaratorInfo())
+ return getDeclaratorInfo()->getType();
+ return getType();
+ }
/// setOwningFunction - Sets the function declaration that owns this
/// ParmVarDecl. Since ParmVarDecls are often created before the
@@ -778,41 +785,11 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
- return (D->getKind() == ParmVar ||
- D->getKind() == OriginalParmVar);
+ return (D->getKind() == ParmVar);
}
static bool classof(const ParmVarDecl *D) { return true; }
};
-/// OriginalParmVarDecl - Represent a parameter to a function, when
-/// the type of the parameter has been promoted. This node represents the
-/// parameter to the function with its original type.
-///
-class OriginalParmVarDecl : public ParmVarDecl {
- friend class ParmVarDecl;
-protected:
- QualType OriginalType;
-private:
- OriginalParmVarDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
- DeclaratorInfo *DInfo,
- QualType OT, StorageClass S,
- Expr *DefArg)
- : ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg),
- OriginalType(OT) {}
-public:
- static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,IdentifierInfo *Id,
- QualType T, DeclaratorInfo *DInfo,
- QualType OT, StorageClass S, Expr *DefArg);
-
- void setOriginalType(QualType T) { OriginalType = T; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
- static bool classof(const OriginalParmVarDecl *D) { return true; }
-};
-
/// FunctionDecl - An instance of this class is created to represent a
/// function declaration or definition.
///
@@ -1067,9 +1044,18 @@ public:
StorageClass getStorageClass() const { return StorageClass(SClass); }
void setStorageClass(StorageClass SC) { SClass = SC; }
- bool isInline() const { return IsInline; }
- void setInline(bool I) { IsInline = I; }
+ /// \brief Determine whether the "inline" keyword was specified for this
+ /// function.
+ bool isInlineSpecified() const { return IsInline; }
+
+ /// Set whether the "inline" keyword was specified for this function.
+ void setInlineSpecified(bool I) { IsInline = I; }
+ /// \brief Determine whether this function should be inlined, because it is
+ /// either marked "inline" or is a member function of a C++ class that
+ /// was defined in the class body.
+ bool isInlined() const;
+
bool isInlineDefinitionExternallyVisible() const;
/// isOverloadedOperator - Whether this function declaration
@@ -1146,7 +1132,17 @@ public:
return TemplateOrSpecialization.
dyn_cast<FunctionTemplateSpecializationInfo*>();
}
-
+
+ /// \brief Determines whether this function is a function template
+ /// specialization or a member of a class template specialization that can
+ /// be implicitly instantiated.
+ bool isImplicitlyInstantiable() const;
+
+ /// \brief Retrieve the function declaration from which this function could
+ /// be instantiated, if it is an instantiation (rather than a non-template
+ /// or a specialization, for example).
+ FunctionDecl *getTemplateInstantiationPattern() const;
+
/// \brief Retrieve the primary template that this function template
/// specialization either specializes or was instantiated from.
///
@@ -1199,7 +1195,7 @@ public:
/// instantiated from a template; otherwie, returns an invalid source
/// location.
SourceLocation getPointOfInstantiation() const;
-
+
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a member function.
bool isOutOfLine() const;
@@ -1337,20 +1333,29 @@ public:
class TypedefDecl : public TypeDecl {
/// UnderlyingType - This is the type the typedef is set to.
- QualType UnderlyingType;
+ DeclaratorInfo *DInfo;
+
TypedefDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T)
- : TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {}
+ IdentifierInfo *Id, DeclaratorInfo *DInfo)
+ : TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {}
virtual ~TypedefDecl() {}
public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,IdentifierInfo *Id,
- QualType T);
+ SourceLocation L, IdentifierInfo *Id,
+ DeclaratorInfo *DInfo);
+
+ DeclaratorInfo *getTypeDeclaratorInfo() const {
+ return DInfo;
+ }
- QualType getUnderlyingType() const { return UnderlyingType; }
- void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
+ QualType getUnderlyingType() const {
+ return DInfo->getType();
+ }
+ void setTypeDeclaratorInfo(DeclaratorInfo *newType) {
+ DInfo = newType;
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Typedef; }
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 790ea3ca0662..e1fae8f2ae67 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
namespace clang {
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
index 79a0d368288c..3ef3cc3f0975 100644
--- a/include/clang/AST/DeclNodes.def
+++ b/include/clang/AST/DeclNodes.def
@@ -103,7 +103,6 @@ ABSTRACT_DECL(Named, Decl)
DECL(Var, DeclaratorDecl)
DECL(ImplicitParam, VarDecl)
DECL(ParmVar, VarDecl)
- DECL(OriginalParmVar, ParmVarDecl)
DECL(NonTypeTemplateParm, VarDecl)
DECL(Template, NamedDecl)
DECL(FunctionTemplate, TemplateDecl)
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 729a2f138303..bcd28eab039f 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -347,6 +347,8 @@ public:
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
+ ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(
+ IdentifierInfo *PropertyId) const;
// Marks the end of the container.
SourceLocation getAtEndLoc() const { return AtEndLoc; }
@@ -862,7 +864,7 @@ public:
};
class ObjCImplDecl : public ObjCContainerDecl {
- /// Class interface for this category implementation
+ /// Class interface for this class/category implementation
ObjCInterfaceDecl *ClassInterface;
protected:
@@ -935,14 +937,20 @@ public:
SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface);
- /// getIdentifier - Get the identifier that names the class
+ /// getIdentifier - Get the identifier that names the category
/// interface associated with this implementation.
+ /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
+ /// to mean something different. For example:
+ /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the class interface name, whereas
+ /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the category name.
IdentifierInfo *getIdentifier() const {
return Id;
}
void setIdentifier(IdentifierInfo *II) { Id = II; }
- ObjCCategoryDecl *getCategoryClass() const;
+ ObjCCategoryDecl *getCategoryDecl() const;
/// getName - Get the name of identifier for the class interface associated
/// with this implementation as a StringRef.
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 8d44676124fb..f1a27933a1b3 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -15,8 +15,7 @@
#define LLVM_CLANG_AST_DECLTEMPLATE_H
#include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/FoldingSet.h"
+#include "clang/AST/TemplateBase.h"
#include "llvm/ADT/PointerUnion.h"
#include <limits>
@@ -91,6 +90,13 @@ public:
/// arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
+ /// \brief Get the depth of this template parameter list in the set of
+ /// template parameter lists.
+ ///
+ /// The first template parameter list in a declaration will have depth 0,
+ /// the second template parameter list will have depth 1, etc.
+ unsigned getDepth() const;
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -100,251 +106,6 @@ public:
}
};
-/// \brief Represents a template argument within a class template
-/// specialization.
-class TemplateArgument {
- union {
- uintptr_t TypeOrValue;
- struct {
- char Value[sizeof(llvm::APSInt)];
- void *Type;
- } Integer;
- struct {
- TemplateArgument *Args;
- unsigned NumArgs;
- bool CopyArgs;
- } Args;
- };
-
- /// \brief Location of the beginning of this template argument.
- SourceLocation StartLoc;
-
-public:
- /// \brief The type of template argument we're storing.
- enum ArgKind {
- Null = 0,
- /// The template argument is a type. Its value is stored in the
- /// TypeOrValue field.
- Type = 1,
- /// The template argument is a declaration
- Declaration = 2,
- /// The template argument is an integral value stored in an llvm::APSInt.
- Integral = 3,
- /// The template argument is a value- or type-dependent expression
- /// stored in an Expr*.
- Expression = 4,
-
- /// The template argument is actually a parameter pack. Arguments are stored
- /// in the Args struct.
- Pack = 5
- } Kind;
-
- /// \brief Construct an empty, invalid template argument.
- TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
-
- /// \brief Construct a template type argument.
- TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
- TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- StartLoc = Loc;
- }
-
- /// \brief Construct a template argument that refers to a
- /// declaration, which is either an external declaration or a
- /// template declaration.
- TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
- // FIXME: Need to be sure we have the "canonical" declaration!
- TypeOrValue = reinterpret_cast<uintptr_t>(D);
- StartLoc = Loc;
- }
-
- /// \brief Construct an integral constant template argument.
- TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
- QualType Type)
- : Kind(Integral) {
- new (Integer.Value) llvm::APSInt(Value);
- Integer.Type = Type.getAsOpaquePtr();
- StartLoc = Loc;
- }
-
- /// \brief Construct a template argument that is an expression.
- ///
- /// This form of template argument only occurs in template argument
- /// lists used for dependent types and for expression; it will not
- /// occur in a non-dependent, canonical template argument list.
- TemplateArgument(Expr *E);
-
- /// \brief Copy constructor for a template argument.
- TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
- if (Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else if (Kind == Pack) {
- Args.NumArgs = Other.Args.NumArgs;
- Args.Args = new TemplateArgument[Args.NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = Other.Args.Args[I];
- }
- else
- TypeOrValue = Other.TypeOrValue;
- StartLoc = Other.StartLoc;
- }
-
- TemplateArgument& operator=(const TemplateArgument& Other) {
- // FIXME: Does not provide the strong guarantee for exception
- // safety.
- using llvm::APSInt;
-
- // FIXME: Handle Packs
- assert(Kind != Pack && "FIXME: Handle packs");
- assert(Other.Kind != Pack && "FIXME: Handle packs");
-
- if (Kind == Other.Kind && Kind == Integral) {
- // Copy integral values.
- *this->getAsIntegral() = *Other.getAsIntegral();
- Integer.Type = Other.Integer.Type;
- } else {
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
-
- Kind = Other.Kind;
-
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else
- TypeOrValue = Other.TypeOrValue;
- }
- StartLoc = Other.StartLoc;
-
- return *this;
- }
-
- ~TemplateArgument() {
- using llvm::APSInt;
-
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
- else if (Kind == Pack && Args.CopyArgs)
- delete[] Args.Args;
- }
-
- /// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return Kind; }
-
- /// \brief Determine whether this template argument has no value.
- bool isNull() const { return Kind == Null; }
-
- /// \brief Retrieve the template argument as a type.
- QualType getAsType() const {
- if (Kind != Type)
- return QualType();
-
- return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
- }
-
- /// \brief Retrieve the template argument as a declaration.
- Decl *getAsDecl() const {
- if (Kind != Declaration)
- return 0;
- return reinterpret_cast<Decl *>(TypeOrValue);
- }
-
- /// \brief Retrieve the template argument as an integral value.
- llvm::APSInt *getAsIntegral() {
- if (Kind != Integral)
- return 0;
- return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
- }
-
- const llvm::APSInt *getAsIntegral() const {
- return const_cast<TemplateArgument*>(this)->getAsIntegral();
- }
-
- /// \brief Retrieve the type of the integral value.
- QualType getIntegralType() const {
- if (Kind != Integral)
- return QualType();
-
- return QualType::getFromOpaquePtr(Integer.Type);
- }
-
- void setIntegralType(QualType T) {
- assert(Kind == Integral &&
- "Cannot set the integral type of a non-integral template argument");
- Integer.Type = T.getAsOpaquePtr();
- };
-
- /// \brief Retrieve the template argument as an expression.
- Expr *getAsExpr() const {
- if (Kind != Expression)
- return 0;
-
- return reinterpret_cast<Expr *>(TypeOrValue);
- }
-
- /// \brief Iterator that traverses the elements of a template argument pack.
- typedef const TemplateArgument * pack_iterator;
-
- /// \brief Iterator referencing the first argument of a template argument
- /// pack.
- pack_iterator pack_begin() const {
- assert(Kind == Pack);
- return Args.Args;
- }
-
- /// \brief Iterator referencing one past the last argument of a template
- /// argument pack.
- pack_iterator pack_end() const {
- assert(Kind == Pack);
- return Args.Args + Args.NumArgs;
- }
-
- /// \brief The number of template arguments in the given template argument
- /// pack.
- unsigned pack_size() const {
- assert(Kind == Pack);
- return Args.NumArgs;
- }
-
- /// \brief Retrieve the location where the template argument starts.
- SourceLocation getLocation() const { return StartLoc; }
-
- /// \brief Construct a template argument pack.
- void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
-
- /// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const {
- ID.AddInteger(Kind);
- switch (Kind) {
- case Null:
- break;
-
- case Type:
- getAsType().Profile(ID);
- break;
-
- case Declaration:
- ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
- break;
-
- case Integral:
- getAsIntegral()->Profile(ID);
- getIntegralType().Profile(ID);
- break;
-
- case Expression:
- getAsExpr()->Profile(ID, Context, true);
- break;
-
- case Pack:
- ID.AddInteger(Args.NumArgs);
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I].Profile(ID, Context);
- }
- }
-};
-
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
TemplateArgument *StructuredArgs;
@@ -811,11 +572,8 @@ class TemplateTypeParmDecl : public TypeDecl {
/// \brief Whether this is a parameter pack.
bool ParameterPack : 1;
- /// \brief The location of the default argument, if any.
- SourceLocation DefaultArgumentLoc;
-
/// \brief The default template argument, if any.
- QualType DefaultArgument;
+ DeclaratorInfo *DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type, bool ParameterPack)
@@ -837,13 +595,16 @@ public:
/// \brief Determine whether this template parameter has a default
/// argument.
- bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
+ bool hasDefaultArgument() const { return DefaultArgument != 0; }
/// \brief Retrieve the default argument, if any.
- QualType getDefaultArgument() const { return DefaultArgument; }
+ QualType getDefaultArgument() const { return DefaultArgument->getType(); }
- /// \brief Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
+ /// \brief Retrieves the default argument's source information, if any.
+ DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
+
+ /// \brief Retrieves the location of the default argument declaration.
+ SourceLocation getDefaultArgumentLoc() const;
/// \brief Determines whether the default argument was inherited
/// from a previous declaration of this template.
@@ -852,13 +613,23 @@ public:
/// \brief Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
- void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
- bool Inherited) {
+ void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) {
DefaultArgument = DefArg;
- DefaultArgumentLoc = DefArgLoc;
InheritedDefault = Inherited;
}
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgument = 0;
+ InheritedDefault = false;
+ }
+
+ /// \brief Retrieve the depth of the template parameter.
+ unsigned getDepth() const;
+
+ /// \brief Retrieve the index of the template parameter.
+ unsigned getIndex() const;
+
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const { return ParameterPack; }
@@ -1150,17 +921,32 @@ class ClassTemplatePartialSpecializationDecl
/// \brief The list of template parameters
TemplateParameterList* TemplateParams;
+ /// \brief The source info for the template arguments as written.
+ TemplateArgumentLoc *ArgsAsWritten;
+ unsigned NumArgsAsWritten;
+
+ /// \brief The class template partial specialization from which this
+ /// class template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this class template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
ClassTemplatePartialSpecializationDecl(ASTContext &Context,
DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
+ TemplateArgumentLoc *ArgInfos,
+ unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl)
: ClassTemplateSpecializationDecl(Context,
ClassTemplatePartialSpecialization,
DC, L, SpecializedTemplate, Builder,
PrevDecl),
- TemplateParams(Params) { }
+ TemplateParams(Params), ArgsAsWritten(ArgInfos),
+ NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { }
public:
static ClassTemplatePartialSpecializationDecl *
@@ -1168,6 +954,8 @@ public:
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
+ TemplateArgumentLoc *ArgInfos,
+ unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl);
/// Get the list of template parameters
@@ -1175,6 +963,80 @@ public:
return TemplateParams;
}
+ /// Get the template arguments as written.
+ TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// Get the number of template arguments as written.
+ unsigned getNumTemplateArgsAsWritten() const {
+ return NumArgsAsWritten;
+ }
+
+ /// \brief Retrieve the member class template partial specialization from
+ /// which this particular class template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*> { }; // #1
+ /// };
+ ///
+ /// Outer<float>::Inner<int*> ii;
+ /// \endcode
+ ///
+ /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
+ /// end up instantiating the partial specialization
+ /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
+ /// template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this class template partial specialization
+ /// template was a specialization of a member partial specialization.
+ ///
+ /// In the following example, the member template partial specialization
+ /// \c X<int>::Inner<T*> is a member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*>;
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// struct X<int>::Inner<T*> { /* ... */ };
+ /// \endcode
+ bool isMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
// FIXME: Add Profile support!
static bool classof(const Decl *D) {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 0d09ea325c31..2a87f5883588 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -34,6 +34,7 @@ namespace clang {
class BlockDecl;
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
+ class TemplateArgumentLoc;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
@@ -134,7 +135,7 @@ public:
/// with location to warn on and the source range[s] to report with the
/// warning.
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2) const;
+ SourceRange &R2, ASTContext &Ctx) const;
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
/// incomplete type other than void. Nonarray expressions that can be lvalues:
@@ -241,6 +242,10 @@ public:
/// in Result.
bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
+ /// EvaluateAsAny - The same as Evaluate, except that it also succeeds on
+ /// stack based objects.
+ bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const;
+
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
bool isEvaluatable(ASTContext &Ctx) const;
@@ -322,47 +327,221 @@ public:
// Primary Expressions.
//===----------------------------------------------------------------------===//
+/// \brief Represents the qualifier that may precede a C++ name, e.g., the
+/// "std::" in "std::sort".
+struct NameQualifier {
+ /// \brief The nested name specifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The source range covered by the nested name specifier.
+ SourceRange Range;
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+struct ExplicitTemplateArgumentList {
+ /// \brief The source location of the left angle bracket ('<');
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>');
+ SourceLocation RAngleLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ /// The actual template arguments (if any) are stored after the
+ /// ExplicitTemplateArgumentList structure.
+ unsigned NumTemplateArgs;
+
+ /// \brief Retrieve the template arguments
+ TemplateArgumentLoc *getTemplateArgs() {
+ return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
+ }
+
+ /// \brief Retrieve the template arguments
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
+ }
+};
+
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
/// enum, etc.
class DeclRefExpr : public Expr {
- NamedDecl *D;
+ enum {
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has a C++ nested-name-specifier.
+ HasQualifierFlag = 0x01,
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has an explicit C++ template argument list.
+ HasExplicitTemplateArgumentListFlag = 0x02
+ };
+
+ // DecoratedD - The declaration that we are referencing, plus two bits to
+ // indicate whether (1) the declaration's name was explicitly qualified and
+ // (2) the declaration's name was followed by an explicit template
+ // argument list.
+ llvm::PointerIntPair<NamedDecl *, 2> DecoratedD;
+
+ // Loc - The location of the declaration name itself.
SourceLocation Loc;
+ /// \brief Retrieve the qualifier that preceded the declaration name, if any.
+ NameQualifier *getNameQualifier() {
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return 0;
+
+ return reinterpret_cast<NameQualifier *> (this + 1);
+ }
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ const NameQualifier *getNameQualifier() const {
+ return const_cast<DeclRefExpr *>(this)->getNameQualifier();
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0)
+ return 0;
+
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getNameQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList();
+ }
+
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ NamedDecl *D, SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD);
+
protected:
// FIXME: Eventually, this constructor will go away and all subclasses
// will have to provide the type- and value-dependent flags.
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
- Expr(SC, t), D(d), Loc(l) {}
+ Expr(SC, t), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD,
bool VD) :
- Expr(SC, t, TD, VD), D(d), Loc(l) {}
+ Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
public:
// FIXME: Eventually, this constructor will go away and all clients
// will have to provide the type- and value-dependent flags.
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
- Expr(DeclRefExprClass, t), D(d), Loc(l) {}
+ Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
- Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
+ Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
- NamedDecl *getDecl() { return D; }
- const NamedDecl *getDecl() const { return D; }
- void setDecl(NamedDecl *NewD) { D = NewD; }
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ QualType T, bool TD, bool VD);
+
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD);
+
+ NamedDecl *getDecl() { return DecoratedD.getPointer(); }
+ const NamedDecl *getDecl() const { return DecoratedD.getPointer(); }
+ void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ virtual SourceRange getSourceRange() const;
+ /// \brief Determine whether this declaration reference was preceded by a
+ /// C++ nested-name-specifier, e.g., \c N::foo.
+ bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; }
+
+ /// \brief If the name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const {
+ if (!hasQualifier())
+ return SourceRange();
+
+ return getNameQualifier()->Range;
+ }
+
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ if (!hasQualifier())
+ return 0;
+
+ return getNameQualifier()->NNS;
+ }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgumentList() const {
+ return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!hasExplicitTemplateArgumentList())
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgumentList())
+ return 0;
+
+ return getExplicitTemplateArgumentList()->getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgumentList())
+ return 0;
+
+ return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!hasExplicitTemplateArgumentList())
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->RAngleLoc;
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass ||
- T->getStmtClass() == CXXConditionDeclExprClass ||
- T->getStmtClass() == QualifiedDeclRefExprClass;
+ T->getStmtClass() == CXXConditionDeclExprClass;
}
static bool classof(const DeclRefExpr *) { return true; }
@@ -797,7 +976,7 @@ class SizeOfAlignOfExpr : public Expr {
bool isSizeof : 1; // true if sizeof, false if alignof.
bool isType : 1; // true if operand is a type, false if an expression
union {
- void *Ty;
+ DeclaratorInfo *Ty;
Stmt *Ex;
} Argument;
SourceLocation OpLoc, RParenLoc;
@@ -806,15 +985,15 @@ protected:
virtual void DoDestroy(ASTContext& C);
public:
- SizeOfAlignOfExpr(bool issizeof, QualType T,
+ SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- T->isDependentType()),
+ DInfo->getType()->isDependentType()),
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
- Argument.Ty = T.getAsOpaquePtr();
+ Argument.Ty = DInfo;
}
SizeOfAlignOfExpr(bool issizeof, Expr *E,
@@ -837,8 +1016,11 @@ public:
bool isArgumentType() const { return isType; }
QualType getArgumentType() const {
+ return getArgumentTypeInfo()->getType();
+ }
+ DeclaratorInfo *getArgumentTypeInfo() const {
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
- return QualType::getFromOpaquePtr(Argument.Ty);
+ return Argument.Ty;
}
Expr *getArgumentExpr() {
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
@@ -849,8 +1031,8 @@ public:
}
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
- void setArgument(QualType T) {
- Argument.Ty = T.getAsOpaquePtr();
+ void setArgument(DeclaratorInfo *DInfo) {
+ Argument.Ty = DInfo;
isType = true;
}
@@ -1062,41 +1244,6 @@ public:
virtual child_iterator child_end();
};
-/// \brief Represents the qualifier that may precede a C++ name, e.g., the
-/// "std::" in "std::sort".
-struct NameQualifier {
- /// \brief The nested name specifier.
- NestedNameSpecifier *NNS;
-
- /// \brief The source range covered by the nested name specifier.
- SourceRange Range;
-};
-
-/// \brief Represents an explicit template argument list in C++, e.g.,
-/// the "<int>" in "sort<int>".
-struct ExplicitTemplateArgumentList {
- /// \brief The source location of the left angle bracket ('<');
- SourceLocation LAngleLoc;
-
- /// \brief The source location of the right angle bracket ('>');
- SourceLocation RAngleLoc;
-
- /// \brief The number of template arguments in TemplateArgs.
- /// The actual template arguments (if any) are stored after the
- /// ExplicitTemplateArgumentList structure.
- unsigned NumTemplateArgs;
-
- /// \brief Retrieve the template arguments
- TemplateArgument *getTemplateArgs() {
- return reinterpret_cast<TemplateArgument *> (this + 1);
- }
-
- /// \brief Retrieve the template arguments
- const TemplateArgument *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgument *> (this + 1);
- }
-};
-
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr : public Expr {
@@ -1161,7 +1308,7 @@ class MemberExpr : public Expr {
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
bool has_explicit, SourceLocation langle,
- const TemplateArgument *targs, unsigned numtargs,
+ const TemplateArgumentLoc *targs, unsigned numtargs,
SourceLocation rangle, QualType ty);
public:
@@ -1183,7 +1330,7 @@ public:
SourceLocation l,
bool has_explicit,
SourceLocation langle,
- const TemplateArgument *targs,
+ const TemplateArgumentLoc *targs,
unsigned numtargs,
SourceLocation rangle,
QualType ty);
@@ -1240,7 +1387,7 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
+ const TemplateArgumentLoc *getTemplateArgs() const {
if (!HasExplicitTemplateArgumentList)
return 0;
@@ -1388,6 +1535,10 @@ public:
/// member pointer in derived class.
CK_BaseToDerivedMemberPointer,
+ /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
+ /// member pointer in base class.
+ CK_DerivedToBaseMemberPointer,
+
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
CK_UserDefinedConversion,
@@ -1687,7 +1838,9 @@ public:
bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
bool isShiftOp() const { return isShiftOp(Opc); }
- bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
+
+ static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; }
+ bool isBitwiseOp() const { return isBitwiseOp(Opc); }
static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
bool isRelationalOp() const { return isRelationalOp(Opc); }
@@ -1695,6 +1848,9 @@ public:
static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
bool isEqualityOp() const { return isEqualityOp(Opc); }
+ static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; }
+ bool isComparisonOp() const { return isComparisonOp(Opc); }
+
static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
bool isLogicalOp() const { return isLogicalOp(Opc); }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 3f66b1f40bfc..5931a3fcf984 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1061,46 +1061,11 @@ public:
virtual child_iterator child_end();
};
-/// QualifiedDeclRefExpr - A reference to a declared variable,
-/// function, enum, etc., that includes a qualification, e.g.,
-/// "N::foo".
-class QualifiedDeclRefExpr : public DeclRefExpr {
- /// QualifierRange - The source range that covers the
- /// nested-name-specifier.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that qualifies this declaration
- /// name.
- NestedNameSpecifier *NNS;
-
-public:
- QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
- bool VD, SourceRange R, NestedNameSpecifier *NNS)
- : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
- QualifierRange(R), NNS(NNS) { }
-
- /// \brief Retrieve the source range of the nested-name-specifier.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
- /// \brief Retrieve the nested-name-specifier that qualifies this
- /// declaration.
- NestedNameSpecifier *getQualifier() const { return NNS; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(QualifierRange.getBegin(), getLocation());
- }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == QualifiedDeclRefExprClass;
- }
- static bool classof(const QualifiedDeclRefExpr *) { return true; }
-};
-
/// \brief A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
-/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that
-/// it expresses a qualified reference to a declaration such as
+/// UnresolvedDeclRefExpr is similar to eclRefExpr in that
+/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// UnresolvedDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
@@ -1108,8 +1073,8 @@ public:
/// declaration will differ from on instantiation of X<T> to the
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
-/// ("value"). Such expressions will instantiate to
-/// QualifiedDeclRefExprs.
+/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
+/// declaration can be found.
class UnresolvedDeclRefExpr : public Expr {
/// The name of the entity we will be referencing.
DeclarationName Name;
@@ -1126,6 +1091,7 @@ class UnresolvedDeclRefExpr : public Expr {
NestedNameSpecifier *NNS;
/// \brief Whether this expr is an address of (&) operand.
+ /// FIXME: Stash this bit into NNS!
bool IsAddressOfOperand;
public:
@@ -1195,7 +1161,7 @@ class TemplateIdRefExpr : public Expr {
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1206,7 +1172,7 @@ public:
Create(ASTContext &Context, QualType T,
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
+ SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
/// \brief Retrieve the nested name specifier used to qualify the name of
@@ -1232,8 +1198,8 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgument *>(this + 1);
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1477,7 +1443,7 @@ class CXXUnresolvedMemberExpr : public Expr {
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1508,7 +1474,7 @@ public:
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1576,7 +1542,7 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
+ const TemplateArgumentLoc *getTemplateArgs() const {
if (!HasExplicitTemplateArgumentList)
return 0;
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 7490b1d66b3e..5f318ba0b33b 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace clang {
class ASTContext;
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 458af1f14423..1e6871ff3b9c 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -88,6 +88,11 @@ public:
return D;
}
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ const decl_type *getMostRecentDeclaration() const {
+ return getFirstDeclaration()->RedeclLink.getNext();
+ }
+
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
void setPreviousDeclaration(decl_type *PrevDecl) {
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 2d523fffce74..f1aa2cd50f0f 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
#include <iterator>
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 8d7e4b5fc0a3..034029a16971 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -127,7 +127,6 @@ EXPR(CXXDeleteExpr , Expr)
EXPR(CXXPseudoDestructorExpr, Expr)
EXPR(UnresolvedFunctionNameExpr , Expr)
EXPR(UnaryTypeTraitExpr , Expr)
-EXPR(QualifiedDeclRefExpr , DeclRefExpr)
EXPR(UnresolvedDeclRefExpr , Expr)
EXPR(TemplateIdRefExpr , Expr)
EXPR(CXXConstructExpr , Expr)
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
new file mode 100644
index 000000000000..bb14c62d7770
--- /dev/null
+++ b/include/clang/AST/TemplateBase.h
@@ -0,0 +1,366 @@
+//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides definitions which are common for all kinds of
+// template representation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
+#define LLVM_CLANG_AST_TEMPLATEBASE_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/Type.h"
+
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
+namespace clang {
+
+class Decl;
+class Expr;
+class DeclaratorInfo;
+
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ TemplateArgument *Args;
+ unsigned NumArgs;
+ bool CopyArgs;
+ } Args;
+ };
+
+public:
+ /// \brief The type of template argument we're storing.
+ enum ArgKind {
+ Null = 0,
+ /// The template argument is a type. Its value is stored in the
+ /// TypeOrValue field.
+ Type = 1,
+ /// The template argument is a declaration
+ Declaration = 2,
+ /// The template argument is an integral value stored in an llvm::APSInt.
+ Integral = 3,
+ /// The template argument is a value- or type-dependent expression
+ /// stored in an Expr*.
+ Expression = 4,
+
+ /// The template argument is actually a parameter pack. Arguments are stored
+ /// in the Args struct.
+ Pack = 5
+ } Kind;
+
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() : TypeOrValue(0), Kind(Null) { }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(QualType T) : Kind(Type) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ }
+
+ /// \brief Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
+ TemplateArgument(Decl *D) : Kind(Declaration) {
+ // FIXME: Need to be sure we have the "canonical" declaration!
+ TypeOrValue = reinterpret_cast<uintptr_t>(D);
+ }
+
+ /// \brief Construct an integral constant template argument.
+ TemplateArgument(const llvm::APSInt &Value, QualType Type)
+ : Kind(Integral) {
+ new (Integer.Value) llvm::APSInt(Value);
+ Integer.Type = Type.getAsOpaquePtr();
+ }
+
+ /// \brief Construct a template argument that is an expression.
+ ///
+ /// This form of template argument only occurs in template argument
+ /// lists used for dependent types and for expression; it will not
+ /// occur in a non-dependent, canonical template argument list.
+ TemplateArgument(Expr *E) : Kind(Expression) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(E);
+ }
+
+ /// \brief Copy constructor for a template argument.
+ TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ if (Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = new TemplateArgument[Args.NumArgs];
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I] = Other.Args.Args[I];
+ }
+ else
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ TemplateArgument& operator=(const TemplateArgument& Other) {
+ // FIXME: Does not provide the strong guarantee for exception
+ // safety.
+ using llvm::APSInt;
+
+ // FIXME: Handle Packs
+ assert(Kind != Pack && "FIXME: Handle packs");
+ assert(Other.Kind != Pack && "FIXME: Handle packs");
+
+ if (Kind == Other.Kind && Kind == Integral) {
+ // Copy integral values.
+ *this->getAsIntegral() = *Other.getAsIntegral();
+ Integer.Type = Other.Integer.Type;
+ } else {
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+
+ Kind = Other.Kind;
+
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ return *this;
+ }
+
+ ~TemplateArgument() {
+ using llvm::APSInt;
+
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+ else if (Kind == Pack && Args.CopyArgs)
+ delete[] Args.Args;
+ }
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return Kind; }
+
+ /// \brief Determine whether this template argument has no value.
+ bool isNull() const { return Kind == Null; }
+
+ /// \brief Retrieve the template argument as a type.
+ QualType getAsType() const {
+ if (Kind != Type)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+ }
+
+ /// \brief Retrieve the template argument as a declaration.
+ Decl *getAsDecl() const {
+ if (Kind != Declaration)
+ return 0;
+ return reinterpret_cast<Decl *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the template argument as an integral value.
+ llvm::APSInt *getAsIntegral() {
+ if (Kind != Integral)
+ return 0;
+ return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+ }
+
+ const llvm::APSInt *getAsIntegral() const {
+ return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ if (Kind != Integral)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ void setIntegralType(QualType T) {
+ assert(Kind == Integral &&
+ "Cannot set the integral type of a non-integral template argument");
+ Integer.Type = T.getAsOpaquePtr();
+ };
+
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ if (Kind != Expression)
+ return 0;
+
+ return reinterpret_cast<Expr *>(TypeOrValue);
+ }
+
+ /// \brief Iterator that traverses the elements of a template argument pack.
+ typedef const TemplateArgument * pack_iterator;
+
+ /// \brief Iterator referencing the first argument of a template argument
+ /// pack.
+ pack_iterator pack_begin() const {
+ assert(Kind == Pack);
+ return Args.Args;
+ }
+
+ /// \brief Iterator referencing one past the last argument of a template
+ /// argument pack.
+ pack_iterator pack_end() const {
+ assert(Kind == Pack);
+ return Args.Args + Args.NumArgs;
+ }
+
+ /// \brief The number of template arguments in the given template argument
+ /// pack.
+ unsigned pack_size() const {
+ assert(Kind == Pack);
+ return Args.NumArgs;
+ }
+
+ /// \brief Construct a template argument pack.
+ void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+
+ /// \brief Used to insert TemplateArguments into FoldingSets.
+ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
+};
+
+/// Location information for a TemplateArgument.
+struct TemplateArgumentLocInfo {
+private:
+ union {
+ Expr *Expression;
+ DeclaratorInfo *Declarator;
+ };
+
+#ifndef NDEBUG
+ enum Kind {
+ K_None,
+ K_DeclaratorInfo,
+ K_Expression
+ } Kind;
+#endif
+
+public:
+ TemplateArgumentLocInfo()
+ : Expression(0)
+#ifndef NDEBUG
+ , Kind(K_None)
+#endif
+ {}
+
+ TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
+ : Declarator(DInfo)
+#ifndef NDEBUG
+ , Kind(K_DeclaratorInfo)
+#endif
+ {}
+
+ TemplateArgumentLocInfo(Expr *E)
+ : Expression(E)
+#ifndef NDEBUG
+ , Kind(K_Expression)
+#endif
+ {}
+
+ DeclaratorInfo *getAsDeclaratorInfo() const {
+ assert(Kind == K_DeclaratorInfo);
+ return Declarator;
+ }
+
+ Expr *getAsExpr() const {
+ assert(Kind == K_Expression);
+ return Expression;
+ }
+
+#ifndef NDEBUG
+ void validateForArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Type:
+ assert(Kind == K_DeclaratorInfo);
+ break;
+ case TemplateArgument::Expression:
+ case TemplateArgument::Declaration:
+ assert(Kind == K_Expression);
+ break;
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ assert(Kind == K_None);
+ break;
+ case TemplateArgument::Null:
+ llvm::llvm_unreachable("source info for null template argument?");
+ }
+ }
+#endif
+};
+
+/// Location wrapper for a TemplateArgument. TemplateArgument is to
+/// TemplateArgumentLoc as Type is to TypeLoc.
+class TemplateArgumentLoc {
+ TemplateArgument Argument;
+ TemplateArgumentLocInfo LocInfo;
+
+public:
+ TemplateArgumentLoc() {}
+
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ TemplateArgumentLocInfo Opaque)
+ : Argument(Argument), LocInfo(Opaque) {
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
+ : Argument(Argument), LocInfo(DInfo) {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
+ : Argument(Argument), LocInfo(E) {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ }
+
+ /// \brief - Fetches the start location of the argument.
+ SourceLocation getLocation() const {
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief - Fetches the full source range of the argument.
+ SourceRange getSourceRange() const;
+
+ const TemplateArgument &getArgument() const {
+ return Argument;
+ }
+
+ TemplateArgumentLocInfo getLocInfo() const {
+ return LocInfo;
+ }
+
+ DeclaratorInfo *getSourceDeclaratorInfo() const {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ return LocInfo.getAsDeclaratorInfo();
+ }
+
+ Expr *getSourceExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ return LocInfo.getAsExpr();
+ }
+
+ Expr *getSourceDeclExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Declaration);
+ return LocInfo.getAsExpr();
+ }
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index 66ff34cf1e31..8ef8fb51416c 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
+#include "clang/Basic/OperatorKinds.h"
namespace llvm {
class raw_ostream;
@@ -224,10 +225,24 @@ public:
class DependentTemplateName : public llvm::FoldingSetNode {
/// \brief The nested name specifier that qualifies the template
/// name.
- NestedNameSpecifier *Qualifier;
+ ///
+ /// The bit stored in this qualifier describes whether the \c Name field
+ /// is interpreted as an IdentifierInfo pointer (when clear) or as an
+ /// overloaded operator kind (when set).
+ llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
/// \brief The dependent template name.
- const IdentifierInfo *Name;
+ union {
+ /// \brief The identifier template name.
+ ///
+ /// Only valid when the bit on \c Qualifier is clear.
+ const IdentifierInfo *Identifier;
+
+ /// \brief The overloaded operator name.
+ ///
+ /// Only valid when the bit on \c Qualifier is set.
+ OverloadedOperatorKind Operator;
+ };
/// \brief The canonical template name to which this dependent
/// template name refers.
@@ -240,30 +255,70 @@ class DependentTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;
DependentTemplateName(NestedNameSpecifier *Qualifier,
- const IdentifierInfo *Name)
- : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { }
+ const IdentifierInfo *Identifier)
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(this) { }
DependentTemplateName(NestedNameSpecifier *Qualifier,
- const IdentifierInfo *Name,
+ const IdentifierInfo *Identifier,
TemplateName Canon)
- : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { }
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(Canon) { }
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(this) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ TemplateName Canon)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(Canon) { }
+
public:
/// \brief Return the nested name specifier that qualifies this name.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
- /// \brief Return the name to which this dependent template name
- /// refers.
- const IdentifierInfo *getName() const { return Name; }
+ /// \brief Determine whether this template name refers to an identifier.
+ bool isIdentifier() const { return !Qualifier.getInt(); }
+ /// \brief Returns the identifier to which this template name refers.
+ const IdentifierInfo *getIdentifier() const {
+ assert(isIdentifier() && "Template name isn't an identifier?");
+ return Identifier;
+ }
+
+ /// \brief Determine whether this template name refers to an overloaded
+ /// operator.
+ bool isOverloadedOperator() const { return Qualifier.getInt(); }
+
+ /// \brief Return the overloaded operator to which this template name refers.
+ OverloadedOperatorKind getOperator() const {
+ assert(isOverloadedOperator() &&
+ "Template name isn't an overloaded operator?");
+ return Operator;
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getQualifier(), getName());
+ if (isIdentifier())
+ Profile(ID, getQualifier(), getIdentifier());
+ else
+ Profile(ID, getQualifier(), getOperator());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Identifier) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(false);
+ ID.AddPointer(Identifier);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- const IdentifierInfo *Name) {
+ OverloadedOperatorKind Operator) {
ID.AddPointer(NNS);
- ID.AddPointer(Name);
+ ID.AddBoolean(true);
+ ID.AddInteger(Operator);
}
};
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index db02a68a984d..daa814739182 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -81,6 +81,7 @@ namespace clang {
class SourceLocation;
class StmtIteratorBase;
class TemplateArgument;
+ class TemplateArgumentLoc;
class QualifiedNameType;
struct PrintingPolicy;
@@ -2275,12 +2276,19 @@ public:
static bool anyDependentTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
+ static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs);
+
/// \brief Print a template argument list, including the '<' and '>'
/// enclosing the template arguments.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs,
const PrintingPolicy &Policy);
+ static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
typedef const TemplateArgument * iterator;
iterator begin() const { return getArgs(); }
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 1d7181b531f8..da7857822e9c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_TYPELOC_H
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateBase.h"
namespace clang {
class ParmVarDecl;
@@ -82,6 +83,19 @@ public:
return Data;
}
+ /// \brief Get the full source range.
+ SourceRange getFullSourceRange() const {
+ SourceLocation End = getSourceRange().getEnd();
+ TypeLoc Cur = *this;
+ while (true) {
+ TypeLoc Next = Cur.getNextTypeLoc();
+ if (Next.isNull()) break;
+ Cur = Next;
+ }
+ return SourceRange(Cur.getSourceRange().getBegin(), End);
+ }
+
+ /// \brief Get the local source range.
SourceRange getSourceRange() const {
return getSourceRangeImpl(*this);
}
@@ -761,6 +775,10 @@ public:
getLocalData()->RBracketLoc = Loc;
}
+ SourceRange getBracketsRange() const {
+ return SourceRange(getLBracketLoc(), getRBracketLoc());
+ }
+
Expr *getSizeExpr() const {
return getLocalData()->Size;
}
@@ -810,6 +828,118 @@ class VariableArrayTypeLoc :
VariableArrayType> {
};
+
+// Location information for a TemplateName. Rudimentary for now.
+struct TemplateNameLocInfo {
+ SourceLocation NameLoc;
+};
+
+struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+};
+
+class TemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ TemplateSpecializationTypeLoc,
+ TemplateSpecializationType,
+ TemplateSpecializationLocInfo> {
+public:
+ SourceLocation getLAngleLoc() const {
+ return getLocalData()->LAngleLoc;
+ }
+ void setLAngleLoc(SourceLocation Loc) {
+ getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return getLocalData()->RAngleLoc;
+ }
+ void setRAngleLoc(SourceLocation Loc) {
+ getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumArgs() const {
+ return getTypePtr()->getNumArgs();
+ }
+ void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
+#ifndef NDEBUG
+ AI.validateForArgument(getTypePtr()->getArg(i));
+#endif
+ getArgInfos()[i] = AI;
+ }
+ TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
+ return getArgInfos()[i];
+ }
+
+ TemplateArgumentLoc getArgLoc(unsigned i) const {
+ return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ return getLocalData()->NameLoc;
+ }
+ void setTemplateNameLoc(SourceLocation Loc) {
+ getLocalData()->NameLoc = Loc;
+ }
+
+ /// \brief - Copy the location information from the given info.
+ void copy(TemplateSpecializationTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+
+ // We're potentially copying Expr references here. We don't
+ // bother retaining them because DeclaratorInfos live forever, so
+ // as long as the Expr was retained when originally written into
+ // the TypeLoc, we're okay.
+ memcpy(Data, Loc.Data, size);
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getTemplateNameLoc(), getRAngleLoc());
+ }
+
+ void initializeLocal(SourceLocation Loc) {
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ setTemplateNameLoc(Loc);
+
+ for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
+ TemplateArgumentLocInfo Info;
+#ifndef NDEBUG
+ // If asserts are enabled, be sure to initialize the argument
+ // loc with the right kind of pointer.
+ switch (getTypePtr()->getArg(i).getKind()) {
+ case TemplateArgument::Expression:
+ case TemplateArgument::Declaration:
+ Info = TemplateArgumentLocInfo((Expr*) 0);
+ break;
+
+ case TemplateArgument::Type:
+ Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
+ break;
+
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ // K_None is fine.
+ break;
+ }
+#endif
+ getArgInfos()[i] = Info;
+ }
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+private:
+ TemplateArgumentLocInfo *getArgInfos() const {
+ return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
+ }
+};
+
// None of these types have proper implementations yet.
class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
@@ -861,11 +991,6 @@ class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc,
ElaboratedType> {
};
-class TemplateSpecializationTypeLoc
- : public TypeSpecTypeLoc<TemplateSpecializationTypeLoc,
- TemplateSpecializationType> {
-};
-
class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc,
QualifiedNameType> {
};
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index fabeea38d597..5edfe6fea8db 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -17,7 +17,6 @@
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Entity.h"
#include "clang/Index/Program.h"
-#include "clang/Frontend/ASTUnit.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/STLExtras.h"
@@ -87,7 +86,7 @@ public:
CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
- void addTU(ASTUnit &AST);
+ void addTU(ASTContext &AST);
idx::Program &getProgram() { return Prog; }
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h
index 8e02ccf38209..66e850a91444 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h
@@ -80,6 +80,8 @@ protected:
: Kind(k), Ctx(ctx), Parent(parent) {}
public:
+ virtual ~LocationContext() {}
+
ContextKind getKind() const { return Kind; }
AnalysisContext *getAnalysisContext() const { return Ctx; }
@@ -102,7 +104,7 @@ public:
return Ctx->getSelfDecl();
}
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Kind, Ctx, Parent);
}
@@ -119,10 +121,13 @@ public:
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
: LocationContext(StackFrame, ctx, parent), CallSite(s) {}
+
+ virtual ~StackFrameContext() {}
+
Stmt const *getCallSite() const { return CallSite; }
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisContext(), getParent(), CallSite);
}
@@ -141,8 +146,10 @@ public:
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
: LocationContext(Scope, ctx, parent), Enter(s) {}
+
+ virtual ~ScopeContext() {}
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisContext(), getParent(), Enter);
}
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index 1434fce811d1..914118cb430d 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -19,6 +19,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "clang/Analysis/PathSensitive/BugType.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
@@ -183,38 +184,6 @@ public:
const_iterator end() const { return const_iterator(Reports.end()); }
};
-class BugType {
-private:
- const std::string Name;
- const std::string Category;
- llvm::FoldingSet<BugReportEquivClass> EQClasses;
- friend class BugReporter;
- bool SuppressonSink;
-public:
- BugType(const char *name, const char* cat)
- : Name(name), Category(cat), SuppressonSink(false) {}
- virtual ~BugType();
-
- // FIXME: Should these be made strings as well?
- const std::string& getName() const { return Name; }
- const std::string& getCategory() const { return Category; }
-
- /// isSuppressOnSink - Returns true if bug reports associated with this bug
- /// type should be suppressed if the end node of the report is post-dominated
- /// by a sink node.
- bool isSuppressOnSink() const { return SuppressonSink; }
- void setSuppressOnSink(bool x) { SuppressonSink = x; }
-
- virtual void FlushReports(BugReporter& BR);
-
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
- iterator begin() { return EQClasses.begin(); }
- iterator end() { return EQClasses.end(); }
-
- typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
- const_iterator begin() const { return EQClasses.begin(); }
- const_iterator end() const { return EQClasses.end(); }
-};
//===----------------------------------------------------------------------===//
// Specialized subclasses of BugReport.
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h
new file mode 100644
index 000000000000..46b3edd3172e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/BugType.h
@@ -0,0 +1,86 @@
+//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BugType, a class representing a bug type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
+#define LLVM_CLANG_ANALYSIS_BUGTYPE
+
+#include <llvm/ADT/FoldingSet.h>
+#include <string>
+
+namespace clang {
+
+class BugReportEquivClass;
+class BugReporter;
+class BuiltinBugReport;
+class BugReporterContext;
+class GRExprEngine;
+
+class BugType {
+private:
+ const std::string Name;
+ const std::string Category;
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+ friend class BugReporter;
+ bool SuppressonSink;
+public:
+ BugType(const char *name, const char* cat)
+ : Name(name), Category(cat), SuppressonSink(false) {}
+ virtual ~BugType();
+
+ // FIXME: Should these be made strings as well?
+ const std::string& getName() const { return Name; }
+ const std::string& getCategory() const { return Category; }
+
+ /// isSuppressOnSink - Returns true if bug reports associated with this bug
+ /// type should be suppressed if the end node of the report is post-dominated
+ /// by a sink node.
+ bool isSuppressOnSink() const { return SuppressonSink; }
+ void setSuppressOnSink(bool x) { SuppressonSink = x; }
+
+ virtual void FlushReports(BugReporter& BR);
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
+ iterator begin() { return EQClasses.begin(); }
+ iterator end() { return EQClasses.end(); }
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
+ const_iterator begin() const { return EQClasses.begin(); }
+ const_iterator end() const { return EQClasses.end(); }
+};
+
+class BuiltinBug : public BugType {
+ GRExprEngine &Eng;
+protected:
+ const std::string desc;
+public:
+ BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
+ : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
+
+ BuiltinBug(GRExprEngine *eng, const char* n)
+ : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
+
+ const std::string &getDescription() const { return desc; }
+
+ virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
+
+ void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
+
+ virtual void registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode* N,
+ BuiltinBugReport *R) {}
+
+ template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h
index 4e00d69cdba1..3bef08d7545f 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Analysis/PathSensitive/Checker.h
@@ -72,6 +72,10 @@ public:
ASTContext &getASTContext() {
return Eng.getContext();
}
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
return GenerateNode(S, getState(), markAsSink);
@@ -104,16 +108,42 @@ private:
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
const Stmt *stmt,
- ExplodedNode *Pred, bool isPrevisit) {
- CheckerContext C(Dst, Builder, Eng, Pred, getTag(), isPrevisit);
+ ExplodedNode *Pred, void *tag, bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
assert(isPrevisit && "Only previsit supported for now.");
_PreVisit(C, stmt);
}
+ void GR_VisitBind(ExplodedNodeSet &Dst,
+ GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
+ const Stmt *stmt, ExplodedNode *Pred, void *tag,
+ SVal location, SVal val,
+ bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
+ assert(isPrevisit && "Only previsit supported for now.");
+ PreVisitBind(C, stmt, location, val);
+ }
+
public:
virtual ~Checker() {}
- virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) = 0;
- virtual const void *getTag() = 0;
+ virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {}
+
+ // This is a previsit which takes a node returns a node.
+ virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ return Pred;
+ }
+
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *ST,
+ SVal location, SVal val) {}
+
+ virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S,
+ GRExprEngine &Eng) {
+ return Pred;
+ }
+
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h
new file mode 100644
index 000000000000..007ec093b2e0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h
@@ -0,0 +1,28 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class AttrNonNullChecker : public CheckerVisitor<AttrNonNullChecker> {
+ BugType *BT;
+
+public:
+ AttrNonNullChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h
new file mode 100644
index 000000000000..70f3c44165e0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h
@@ -0,0 +1,30 @@
+//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for bad callee at call sites.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class BadCallChecker : public CheckerVisitor<BadCallChecker> {
+ BuiltinBug *BT;
+
+public:
+ BadCallChecker() : BT(0) {}
+
+ static void *getTag();
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
new file mode 100644
index 000000000000..688cf641491d
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
@@ -0,0 +1,53 @@
+//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker and UndefDerefChecker, two builtin checks
+// in GRExprEngine that check for null and undefined pointers at loads
+// and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DEREFCHECKER
+#define LLVM_CLANG_DEREFCHECKER
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+#include "clang/Analysis/PathSensitive/BugType.h"
+
+namespace clang {
+
+class ExplodedNode;
+
+class NullDerefChecker : public Checker {
+ BuiltinBug *BT;
+ llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
+
+public:
+ NullDerefChecker() : BT(0) {}
+ ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,GRExprEngine &Eng);
+
+ static void *getTag();
+ typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator;
+ iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); }
+ iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); }
+};
+
+class UndefDerefChecker : public Checker {
+ BuiltinBug *BT;
+public:
+ UndefDerefChecker() : BT(0) {}
+
+ ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V, GRExprEngine &Eng);
+
+ static void *getTag();
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h
new file mode 100644
index 000000000000..317e43a0e62e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h
@@ -0,0 +1,28 @@
+//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
+ BuiltinBug *BT;
+public:
+ DivZeroChecker() : BT(0) {}
+
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h
new file mode 100644
index 000000000000..7f4e7d524f6c
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h
@@ -0,0 +1,34 @@
+//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for undefined arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNDEFARGCHECKER
+#define LLVM_CLANG_UNDEFARGCHECKER
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> {
+ BugType *BT;
+
+public:
+ UndefinedArgChecker() : BT(0) {}
+
+ static void *getTag();
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
new file mode 100644
index 000000000000..7fee5011c46d
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
@@ -0,0 +1,32 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER
+#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+class UndefinedAssignmentChecker
+ : public CheckerVisitor<UndefinedAssignmentChecker> {
+ BugType *BT;
+public:
+ UndefinedAssignmentChecker() : BT(0) {}
+ static void *getTag();
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *S, SVal location,
+ SVal val);
+};
+}
+#endif
+
diff --git a/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h
new file mode 100644
index 000000000000..b339b3d30141
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h
@@ -0,0 +1,39 @@
+//=== VLASizeChecker.h - Undefined dereference checker ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
+// performs checks for declaration of VLA of undefined or zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+
+namespace clang {
+
+class UndefSizedVLAChecker : public Checker {
+ BugType *BT;
+
+public:
+ UndefSizedVLAChecker() : BT(0) {}
+ static void *getTag();
+ ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+class ZeroSizedVLAChecker : public Checker {
+ BugType *BT;
+
+public:
+ ZeroSizedVLAChecker() : BT(0) {}
+ static void *getTag();
+ ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index e5c61e68c77c..2f2a11a83cea 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -75,7 +75,12 @@ class GRExprEngine : public GRSubEngine {
Selector RaiseSel;
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
- std::vector<Checker*> Checkers;
+
+ typedef llvm::DenseMap<void *, unsigned> CheckerMap;
+ CheckerMap CheckerM;
+
+ typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered;
+ CheckersOrdered Checkers;
/// BR - The BugReporter associated with this engine. It is important that
// this object be placed at the very end of member variables so that its
@@ -126,18 +131,6 @@ public:
// calling a function with the attribute "noreturn".
ErrorNodes NoReturnCalls;
- /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on a symbolic pointer that MAY be NULL.
- ErrorNodes ImplicitNullDeref;
-
- /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on a symbolic pointer that MUST be NULL.
- ErrorNodes ExplicitNullDeref;
-
- /// UndefDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on an undefined value.
- ErrorNodes UndefDeref;
-
/// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
/// constructing a zero-sized VLA where the size may be zero.
ErrorNodes ImplicitBadSizedVLA;
@@ -158,10 +151,6 @@ public:
/// ObjC message expressions where the receiver is undefined (uninitialized).
ErrorNodes UndefReceivers;
- /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
- /// where a pass-by-value argument has an undefined value.
- UndefArgsTy UndefArgs;
-
/// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
/// message expressions where a pass-by-value argument has an undefined
/// value.
@@ -195,6 +184,8 @@ public:
BugReporter& getBugReporter() { return BR; }
+ GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
+
/// setTransferFunctions
void setTransferFunctions(GRTransferFuncs* tf);
@@ -217,8 +208,19 @@ public:
void RegisterInternalChecks();
- void registerCheck(Checker *check) {
- Checkers.push_back(check);
+ template <typename CHECKER>
+ void registerCheck(CHECKER *check) {
+ unsigned entry = Checkers.size();
+ void *tag = CHECKER::getTag();
+ Checkers.push_back(std::make_pair(tag, check));
+ CheckerM[tag] = entry;
+ }
+
+ Checker *lookupChecker(void *tag) const;
+
+ template <typename CHECKER>
+ CHECKER *getChecker() const {
+ return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
bool isRetStackAddr(const ExplodedNode* N) const {
@@ -234,15 +236,15 @@ public:
}
bool isImplicitNullDeref(const ExplodedNode* N) const {
- return N->isSink() && ImplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isExplicitNullDeref(const ExplodedNode* N) const {
- return N->isSink() && ExplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isUndefDeref(const ExplodedNode* N) const {
- return N->isSink() && UndefDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isNoReturnCall(const ExplodedNode* N) const {
@@ -254,13 +256,11 @@ public:
}
bool isBadCall(const ExplodedNode* N) const {
- return N->isSink() && BadCalls.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isUndefArg(const ExplodedNode* N) const {
- return N->isSink() &&
- (UndefArgs.find(const_cast<ExplodedNode*>(N)) != UndefArgs.end() ||
- MsgExprUndefArgs.find(const_cast<ExplodedNode*>(N)) != MsgExprUndefArgs.end());
+ return false;
}
bool isUndefReceiver(const ExplodedNode* N) const {
@@ -279,17 +279,6 @@ public:
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
- typedef ErrorNodes::iterator null_deref_iterator;
- null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
- null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
-
- null_deref_iterator implicit_null_derefs_begin() {
- return ImplicitNullDeref.begin();
- }
- null_deref_iterator implicit_null_derefs_end() {
- return ImplicitNullDeref.end();
- }
-
typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
@@ -312,10 +301,6 @@ public:
return NilReceiverLargerThanVoidPtrRetExplicit.end();
}
- typedef ErrorNodes::iterator undef_deref_iterator;
- undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
- undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
-
typedef ErrorNodes::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
@@ -325,9 +310,6 @@ public:
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
typedef UndefArgsTy::iterator undef_arg_iterator;
- undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
- undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
-
undef_arg_iterator msg_expr_undef_arg_begin() {
return MsgExprUndefArgs.begin();
}
@@ -427,7 +409,12 @@ public:
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
- void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit);
+ void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ bool isPrevisit);
+
+ void CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ SVal location, SVal val, bool isPrevisit);
+
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
@@ -456,7 +443,8 @@ protected:
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls.
@@ -578,8 +566,9 @@ protected:
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
- void EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
- const GRState* St, SVal location, SVal Val);
+ void EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+ const GRState* St, SVal location, SVal Val,
+ bool atDeclInit = false);
public:
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index d8b9d560ccd8..8678ca9b5b9b 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -26,7 +26,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -219,11 +219,9 @@ public:
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
- const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC,
- SVal V) const;
+ const GRState *bindDecl(const VarRegion *VR, SVal V) const;
- const GRState *bindDeclWithNoInit(const VarDecl *VD,
- const LocationContext *LC) const;
+ const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
const GRState *bindLoc(Loc location, SVal V) const;
@@ -602,15 +600,12 @@ inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
}
-inline const GRState *GRState::bindDecl(const VarDecl* VD,
- const LocationContext *LC,
- SVal IVal) const {
- return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal);
+inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
+ return getStateManager().StoreMgr->BindDecl(this, VR, IVal);
}
-inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD,
- const LocationContext *LC) const {
- return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC);
+inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
+ return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR);
}
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
index 5f7b2cb0e327..40c1ed3224f4 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -23,7 +23,6 @@
namespace clang {
class GRExprEngine;
-class BugReporter;
class ObjCMessageExpr;
class GRStmtNodeBuilderRef;
@@ -33,7 +32,7 @@ public:
virtual ~GRTransferFuncs() {}
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
- virtual void RegisterChecks(BugReporter& BR) {}
+ virtual void RegisterChecks(GRExprEngine& Eng) {}
// Calls.
@@ -78,7 +77,7 @@ public:
virtual const GRState* EvalAssume(const GRState *state,
SVal Cond, bool Assumption) {
return state;
- }
+ }
};
GRTransferFuncs *CreateCallInliner(ASTContext &ctx);
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 7a462c579f9f..6ca2e9e9aa68 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -134,12 +134,11 @@ public:
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
- virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
- const LocationContext *LC, SVal initVal) = 0;
+ virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
+ SVal initVal) = 0;
virtual const GRState *BindDeclWithNoInit(const GRState *ST,
- const VarDecl *VD,
- const LocationContext *LC) = 0;
+ const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h
index d3996c6330a2..167a102e94ec 100644
--- a/include/clang/Analysis/PathSensitive/SymbolManager.h
+++ b/include/clang/Analysis/PathSensitive/SymbolManager.h
@@ -18,7 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseSet.h"
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 666e45b847cf..7aaae9c86653 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -16,7 +16,7 @@
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#include "clang/Analysis/CFG.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Casting.h"
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index 3826d3a3acd6..afc63616e9fc 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -57,7 +57,6 @@ public:
DISPATCH_CASE(Function,FunctionDecl)
DISPATCH_CASE(Var,VarDecl)
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
- DISPATCH_CASE(OriginalParmVar,OriginalParmVarDecl) // FIXME: (same)
DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
DISPATCH_CASE(EnumConstant,EnumConstantDecl)
DISPATCH_CASE(Typedef,TypedefDecl)
@@ -70,7 +69,6 @@ public:
DEFAULT_DISPATCH(VarDecl)
DEFAULT_DISPATCH(FunctionDecl)
- DEFAULT_DISPATCH_VARDECL(OriginalParmVarDecl)
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
DEFAULT_DISPATCH(ImplicitParamDecl)
DEFAULT_DISPATCH(EnumConstantDecl)
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 27997858c00c..98c703d94e92 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -329,7 +329,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
-BUILTIN(__builtin_expect, "iii" , "nc")
+BUILTIN(__builtin_expect, "LiLiLi" , "nc")
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
BUILTIN(__builtin_abort, "v", "Fnr")
BUILTIN(__builtin_trap, "v", "nr")
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index cbf9cdbc1599..bb251ad73bd8 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -52,8 +52,4 @@ def warn_integer_too_large_for_signed : Warning<
def note_invalid_subexpr_in_ice : Note<
"subexpression not valid in an integer constant expression">;
-// clang-cc
-def err_pp_I_dash_not_supported : Error<
- "-I- not supported, please use -iquote instead">;
-
}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index dfdf0ff2e733..e2f11041dce2 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -55,6 +55,8 @@ def err_drv_command_signalled : Error<
"%0 command failed due to signal %1 (use -v to see invocation)">;
def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
+def err_drv_I_dash_not_supported : Error<
+ "'%0' not supported, please use -iquote instead">;
def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index e5c73270fdfc..ae8b92394443 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -12,6 +12,7 @@ let Component = "Frontend" in {
def err_fe_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
+def err_fe_error_opening : Error<"error opening '%0': %1">;
def err_fe_error_reading : Error<"error reading '%0'">;
def err_fe_error_reading_stdin : Error<"error reading stdin">;
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
@@ -19,6 +20,8 @@ def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
def err_fe_invalid_code_complete_file
: Error<"cannot locate code-completion file %0">, DefaultFatal;
+def err_fe_dependency_file_requires_MT : Error<
+ "-dependency-file requires at least one -MT option">;
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
def note_fixit_in_macro : Note<
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 3f132c0dabfa..bbc551373d96 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -194,7 +194,8 @@ def err_pp_expected_eol : Error<
"expected end of line in preprocessor expression">;
def err_pp_defined_requires_identifier : Error<
"operator 'defined' requires an identifier">;
-def err_pp_missing_rparen : Error<"missing ')' after 'defined'">;
+def err_pp_missing_lparen : Error<"missing '(' after '%0'">;
+def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
def err_pp_colon_without_question : Error<"':' without preceding '?'">;
def err_pp_division_by_zero : Error<
"division by zero in preprocessor expression">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 19b0ea3932a5..db8d580a2cd7 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -117,6 +117,8 @@ def err_expected_semi_after_static_assert : Error<
"expected ';' after static_assert">;
def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
def err_expected_colon_after : Error<"expected ':' after %0">;
+def err_pointer_to_member_type : Error<
+ "invalid use of pointer to member type after %0">;
def err_label_end_of_compound_statement : Error<
"label at end of compound statement: expected statement">;
def err_expected_string_literal : Error<"expected string literal">;
@@ -124,6 +126,7 @@ def err_expected_asm_operand : Error<
"expected string literal or '[' for asm operand">;
def err_expected_selector_for_method : Error<
"expected selector for Objective-C method">;
+def err_expected_property_name : Error<"expected property name">;
def err_unexpected_at : Error<"unexpected '@' in program">;
@@ -213,7 +216,8 @@ def err_declaration_does_not_declare_param : Error<
def err_no_matching_param : Error<"parameter named %0 is missing">;
/// C++ parser diagnostics
-def err_expected_unqualified_id : Error<"expected unqualified-id">;
+def err_expected_unqualified_id : Error<
+ "expected %select{identifier|unqualified-id}0">;
def err_func_def_no_params : Error<
"function definition does not declare parameters">;
def err_expected_lparen_after_type : Error<
@@ -230,6 +234,8 @@ def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' in class not allowed">;
+def err_ident_in_pseudo_dtor_not_a_type : Error<
+ "identifier %0 in pseudo-destructor expression does not name a type">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -279,6 +285,9 @@ def err_typename_refers_to_non_type_template : Error<
"typename specifier refers to a non-template">;
def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
+def err_explicit_spec_non_template : Error<
+ "explicit %select{specialization|instantiation}0 of non-template "
+ "%select{class|struct|union}1 %2">;
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
@@ -286,7 +295,7 @@ def err_variadic_templates : Error<
// C++ declarations
def err_friend_decl_defines_class : Error<
"cannot define a type in a friend declaration">;
-
+
// 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 7a87e244f77c..99fddb581088 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -264,13 +264,19 @@ def warn_objc_property_copy_missing_on_block : Warning<
"'copy' attribute must be specified for the block property "
"when -fobjc-gc-only is specified">;
def err_use_continuation_class : Error<
- "attribute of property in continuation class of %0 can only be 'readwrite'">;
+ "property declaration in continuation class of %0 is to change a 'readonly' "
+ "property to 'readwrite'">;
def err_continuation_class : Error<"continuation class has no primary class">;
def err_property_type : Error<"property cannot have array or function type %0">;
def error_missing_property_context : Error<
"missing context for property implementation declaration">;
def error_bad_property_decl : Error<
"property implementation must have its declaration in interface %0">;
+def error_category_property : Error<
+ "property declared in category %0 cannot be implemented in "
+ "class implementation">;
+def note_property_declare : Note<
+ "property declared here">;
def error_synthesize_category_decl : Error<
"@synthesize not allowed in a category's implementation">;
def error_missing_property_interface : Error<
@@ -613,6 +619,10 @@ def warn_attribute_wrong_decl_type : Warning<
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
+def err_cconv_knr : Error<
+ "function with no prototype cannot use '%0' calling convention">;
+def err_cconv_varargs : Error<
+ "variadic function cannot use '%0' calling convention">;
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">;
@@ -1014,7 +1024,11 @@ def note_partial_spec_unused_parameter : Note<
def err_partial_spec_ordering_ambiguous : Error<
"ambiguous partial specializations of %0">;
def note_partial_spec_match : Note<"partial specialization matches %0">;
-
+def err_partial_spec_redeclared : Error<
+ "class template partial specialization %0 cannot be redeclared">;
+def note_prev_partial_spec_here : Note<
+ "previous declaration of class template partial specialization %0 is here">;
+
// C++ Function template specializations
def err_function_template_spec_no_match : Error<
"no function template matches function template specialization %0">;
@@ -1326,17 +1340,17 @@ def err_flexible_array_init_nonempty : Error<
def err_flexible_array_init_needs_braces : Error<
"flexible array requires brace-enclosed initializer">;
def err_illegal_decl_array_of_functions : Error<
- "'%0' declared as array of functions">;
+ "'%0' declared as array of functions of type %1">;
def err_illegal_decl_array_incomplete_type : Error<
"array has incomplete element type %0">;
def err_illegal_decl_array_of_references : Error<
- "'%0' declared as array of references">;
+ "'%0' declared as array of references of type %1">;
def err_array_star_outside_prototype : Error<
"star modifier used outside of function prototype">;
def err_illegal_decl_pointer_to_reference : Error<
- "'%0' declared as a pointer to a reference">;
+ "'%0' declared as a pointer to a reference of type %1">;
def err_illegal_decl_mempointer_to_reference : Error<
- "'%0' declared as a member pointer to a reference">;
+ "'%0' declared as a member pointer to a reference of type %1">;
def err_illegal_decl_mempointer_to_void : Error<
"'%0' declared as a member pointer to void">;
def err_illegal_decl_mempointer_in_nonclass : Error<
@@ -1368,6 +1382,8 @@ def err_alignof_incomplete_type : Error<
"invalid application of '__alignof' to an incomplete type %0">;
def err_sizeof_alignof_bitfield : Error<
"invalid application of '%select{sizeof|__alignof}0' to bit-field">;
+def err_offsetof_incomplete_type : Error<
+ "offsetof of incomplete type %0">;
def err_offsetof_record_type : Error<
"offsetof requires struct, union, or class type, %0 invalid">;
def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
@@ -1385,6 +1401,10 @@ def warn_shift_negative : Warning<
def warn_shift_gt_typewidth : Warning<
"shift count >= width of type">;
+def warn_precedence_bitwise_rel : Warning<
+ "%0 has lower precedence than %1; %1 will be evaluated first">,
+ InGroup<Parentheses>;
+
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
"non-fragile ABI">;
@@ -1661,7 +1681,9 @@ def err_bad_new_type : Error<
def err_new_incomplete_type : Error<
"allocation of incomplete type %0">;
def err_new_array_nonconst : Error<
- "only the first dimension of an allocated array may be non-const">;
+ "only the first dimension of an allocated array may have dynamic size">;
+def err_new_paren_array_nonconst : Error<
+ "when type is in parentheses, array cannot have dynamic size">;
def err_array_size_not_integral : Error<
"array size expression must have integral or enumerated type, not %0">;
def err_new_uninitialized_const : Error<
@@ -1709,8 +1731,6 @@ def err_throw_incomplete_ptr : Error<
def err_return_in_constructor_handler : Error<
"return in the catch of a function try block of a constructor is illegal">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
- "identifier %0 in pseudo-destructor expression does not name a type">;
def err_operator_arrow_circular : Error<
"circular pointer delegation detected">;
def err_pseudo_dtor_base_not_scalar : Error<
@@ -2130,6 +2150,10 @@ def warn_ret_stack_addr : Warning<
"address of stack memory associated with local variable %0 returned">;
def warn_ret_stack_ref : Warning<
"reference to stack memory associated with local variable %0 returned">;
+def warn_ret_addr_label : Warning<
+ "returning address of label, which is local">;
+def err_ret_local_block : Error<
+ "returning block that lives on the local stack">;
// For non-floating point, expressions of the form x == x or x != x
@@ -2153,8 +2177,6 @@ def err_return_in_block_expression : Error<
def err_block_returns_array : Error<
"block declared as returning an array">;
-def err_ret_local_block : Error<
- "returning block that lives on the local stack">;
// CFString checking
def err_cfstring_literal_not_string_constant : Error<
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index 2184bf3c457c..6b60f2eec097 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -16,7 +16,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 790b75ba3af3..c0a95051a72d 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -26,7 +26,10 @@ enum OverloadedOperatorKind {
NUM_OVERLOADED_OPERATORS
};
-
+/// \brief Retrieve the spelling of the given overloaded operator, without
+/// the preceding "operator" keyword.
+const char *getOperatorSpelling(OverloadedOperatorKind Operator);
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index e8cc564c8a20..9960d5beb5c1 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -109,7 +109,7 @@ public:
// Add all arguments.
for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
- (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
+ (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
}
// Add all ranges.
@@ -129,13 +129,25 @@ public:
PD.AddTaggedVal(I, Diagnostic::ak_uint);
return PD;
}
-
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ int I) {
+ PD.AddTaggedVal(I, Diagnostic::ak_sint);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const char *S) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string);
+ return PD;
+ }
+
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const SourceRange &R) {
PD.AddSourceRange(R);
return PD;
}
-
+
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N);
};
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 8a69cba066b3..7e9ac531017e 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -16,7 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include <vector>
#include <cassert>
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index b88e2aaba383..e61ef9265cfb 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -17,7 +17,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
#include <vector>
#include <string>
@@ -103,9 +103,9 @@ public:
/// enum. For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
- /// getTypeSigned - Return whether an integer types is signed. Returns true if
+ /// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
- bool getTypeSigned(IntType T) const;
+ bool isTypeSigned(IntType T) const;
/// getPointerWidth - Return the width of pointers on this target, for the
/// specified address space.
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 4084be6c0b42..5370114ee824 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -404,6 +404,7 @@ OPTION("-flax-vector-conversions", flax_vector_conversions, Flag, f_Group, INVAL
OPTION("-flimited-precision=", flimited_precision_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
OPTION("-flto", flto, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmath-errno", fmath_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmerge-all-constants", fmerge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmessage-length=", fmessage_length_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fms-extensions", fms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmudflapth", fmudflapth, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -428,6 +429,7 @@ OPTION("-fno-inline-functions", fno_inline_functions, Flag, clang_ignored_f_Grou
OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -559,6 +561,7 @@ OPTION("-m", m_Joined, Joined, m_Group, INVALID, "", 0, 0, 0)
OPTION("-no-cpp-precomp", no_cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, 0, 0)
OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nobuiltininc", nobuiltininc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0)
@@ -566,7 +569,6 @@ OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostartfiles", nostartfiles, Flag, INVALID, INVALID, "", 0, 0, 0)
-OPTION("-nostdclanginc", nostdclanginc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostdinc", nostdinc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostdlib", nostdlib, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-object", object, Flag, INVALID, INVALID, "", 0, 0, 0)
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 9573777b5f6f..7dfabbadd8fd 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Index/ASTLocation.h"
#include <string>
namespace clang {
@@ -32,6 +33,8 @@ namespace clang {
class ASTContext;
class Decl;
+using namespace idx;
+
/// \brief Utility class for loading a ASTContext from a PCH file.
///
class ASTUnit {
@@ -50,9 +53,11 @@ class ASTUnit {
// FIXME: This is temporary; eventually, CIndex will always do this.
bool OnlyLocalDecls;
+ // Critical optimization when using clang_getCursor().
+ ASTLocation LastLoc;
+
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
- ASTUnit();
public:
ASTUnit(DiagnosticClient *diagClient = NULL);
@@ -80,6 +85,9 @@ public:
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
+ ASTLocation getLastASTLocation() const { return LastLoc; }
+
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename - The PCH file to load.
diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h
index 508af537b1fa..ad53a8d592ba 100644
--- a/include/clang/Frontend/CompileOptions.h
+++ b/include/clang/Frontend/CompileOptions.h
@@ -43,7 +43,8 @@ public:
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
-
+ unsigned MergeAllConstants : 1; // Merge identical constants.
+
/// Inlining - The kind of inlining to perform.
InliningMethod Inlining;
@@ -67,6 +68,7 @@ public:
Inlining = NoInlining;
DisableRedZone = 0;
NoImplicitFloat = 0;
+ MergeAllConstants = 1;
}
};
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
index 36323c260c9a..8b80d1dc11d8 100644
--- a/include/clang/Frontend/DeclXML.def
+++ b/include/clang/Frontend/DeclXML.def
@@ -99,7 +99,7 @@ NODE_XML(FunctionDecl, "Function")
ENUM_XML(FunctionDecl::Static, "static")
ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
END_ENUM_XML
- ATTRIBUTE_OPT_XML(isInline(), "inline")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
ATTRIBUTE_XML(getNumParams(), "num_args")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
@@ -113,7 +113,7 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
- ATTRIBUTE_OPT_XML(isInline(), "inline")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
ATTRIBUTE_XML(getNumParams(), "num_args")
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
new file mode 100644
index 000000000000..58673e4dad6b
--- /dev/null
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -0,0 +1,49 @@
+//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// DiagnosticOptions - Options for controlling the compiler diagnostics
+/// engine.
+class DiagnosticOptions {
+public:
+ unsigned ShowColumn : 1; /// Show column number on diagnostics.
+ unsigned ShowLocation : 1; /// Show source location information.
+ unsigned ShowCarets : 1; /// Show carets in diagnostics.
+ unsigned ShowFixits : 1; /// Show fixit information.
+ unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
+ unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
+ /// diagnostics.
+ unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
+
+ /// Column limit for formatting message diagnostics, or 0 if unused.
+ unsigned MessageLength;
+
+public:
+ DiagnosticOptions() {
+ ShowColumn = 1;
+ ShowLocation = 1;
+ ShowCarets = 1;
+ ShowFixits = 1;
+ ShowSourceRanges = 0;
+ ShowOptionNames = 0;
+ ShowColors = 0;
+ MessageLength = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/InitHeaderSearch.h b/include/clang/Frontend/InitHeaderSearch.h
index a90b4eaf9e2b..48c426825262 100644
--- a/include/clang/Frontend/InitHeaderSearch.h
+++ b/include/clang/Frontend/InitHeaderSearch.h
@@ -73,6 +73,16 @@ public:
/// variables such as CPATH.
void AddDefaultEnvVarPaths(const LangOptions &Lang);
+ // AddDefaultCIncludePaths - Add paths that should always be searched.
+ void AddDefaultCIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
+ // compiling c++.
+ void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultFrameworkIncludePaths - Add the framework paths. Used on darwin.
+ void AddDefaultFrameworkIncludePaths(const llvm::Triple &triple);
+
/// AddDefaultSystemIncludePaths - Adds the default system include paths so
/// that e.g. stdio.h is found.
void AddDefaultSystemIncludePaths(const LangOptions &Lang,
diff --git a/include/clang/Frontend/InitPreprocessor.h b/include/clang/Frontend/InitPreprocessor.h
index eb03602dc57b..b29ee2728a86 100644
--- a/include/clang/Frontend/InitPreprocessor.h
+++ b/include/clang/Frontend/InitPreprocessor.h
@@ -63,7 +63,8 @@ public:
/// environment ready to process a single file. This returns true on error.
///
bool InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions& InitOptions);
+ const PreprocessorInitOptions& InitOptions,
+ bool undef_macros);
} // end namespace clang
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 1e953d671226..b2bb9a13771d 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -18,7 +18,7 @@
#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace clang {
namespace pch {
@@ -496,8 +496,6 @@ namespace clang {
DECL_IMPLICIT_PARAM,
/// \brief A ParmVarDecl record.
DECL_PARM_VAR,
- /// \brief An OriginalParmVarDecl record.
- DECL_ORIGINAL_PARM_VAR,
/// \brief A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
/// \brief A BlockDecl record.
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index cc16970b0040..cc8b3a03e3e8 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -19,6 +19,7 @@
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
@@ -29,7 +30,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <deque>
#include <map>
#include <string>
@@ -542,6 +543,12 @@ public:
/// comments in the source code.
virtual void ReadComments(std::vector<SourceRange> &Comments);
+ /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// given TemplateArgument kind.
+ TemplateArgumentLocInfo
+ GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const RecordData &Record, unsigned &Idx);
+
/// \brief Reads a declarator info from the given record.
virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record,
unsigned &Idx);
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h
index 728e138d9e7c..22427eb67103 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Frontend/PCHWriter.h
@@ -275,6 +275,10 @@ public:
/// \brief Emits a reference to a declarator info.
void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record);
+ /// \brief Emits a template argument location.
+ void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordData &Record);
+
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordData &Record);
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 0fd8d44f72bc..98e5a75c65b9 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -23,42 +23,21 @@ namespace llvm {
}
namespace clang {
-class SourceManager;
+class DiagnosticOptions;
class LangOptions;
+class SourceManager;
class TextDiagnosticPrinter : public DiagnosticClient {
llvm::raw_ostream &OS;
const LangOptions *LangOpts;
+ const DiagnosticOptions *DiagOpts;
+
SourceLocation LastWarningLoc;
FullSourceLoc LastLoc;
bool LastCaretDiagnosticWasNote;
- bool ShowColumn;
- bool CaretDiagnostics;
- bool ShowLocation;
- bool PrintRangeInfo;
- bool PrintDiagnosticOption;
- bool PrintFixItInfo;
- unsigned MessageLength;
- bool UseColors;
-
public:
- TextDiagnosticPrinter(llvm::raw_ostream &os,
- bool showColumn = true,
- bool caretDiagnistics = true, bool showLocation = true,
- bool printRangeInfo = true,
- bool printDiagnosticOption = true,
- bool printFixItInfo = true,
- unsigned messageLength = 0,
- bool useColors = false)
- : OS(os), LangOpts(0),
- LastCaretDiagnosticWasNote(false), ShowColumn(showColumn),
- CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation),
- PrintRangeInfo(printRangeInfo),
- PrintDiagnosticOption(printDiagnosticOption),
- PrintFixItInfo(printFixItInfo),
- MessageLength(messageLength),
- UseColors(useColors) {}
+ TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
void setLangOptions(const LangOptions *LO) {
LangOpts = LO;
diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h
index 36cf56dea203..f8e01f728648 100644
--- a/include/clang/Index/Utils.h
+++ b/include/clang/Index/Utils.h
@@ -18,7 +18,6 @@
namespace clang {
class ASTContext;
class SourceLocation;
- class Decl;
namespace idx {
class ASTLocation;
@@ -28,7 +27,7 @@ namespace idx {
/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
/// location could not be resolved.
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl = 0);
+ ASTLocation *LastLoc = 0);
} // end namespace idx
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index 97656f7d39d6..c4ab5aebf721 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -17,7 +17,7 @@
#include <string>
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace llvm {
class APInt;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 0765ac391be3..35960ff328a6 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -75,6 +75,8 @@ class Preprocessor {
IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
+ IdentifierInfo *Ident__has_include; // __has_include
+ IdentifierInfo *Ident__has_include_next; // __has_include_next
SourceLocation DATELoc, TIMELoc;
unsigned CounterValue; // Next __COUNTER__ value.
@@ -244,7 +246,12 @@ public:
return CurPPLexer == L;
}
- /// getCurrentLexer - Return the current file lexer being lexed from. Note
+ /// getCurrentLexer - Return the current lexer being lexed from. Note
+ /// that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
+
+ /// getCurrentFileLexer - Return the current file lexer being lexed from. Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *getCurrentFileLexer() const;
@@ -622,6 +629,43 @@ public:
/// SourceLocation.
MacroInfo* AllocateMacroInfo(SourceLocation L);
+ /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+ /// checked and spelled filename, e.g. as an operand of #include. This returns
+ /// true if the input filename was in <>'s or false if it were in ""'s. The
+ /// caller is expected to provide a buffer that is large enough to hold the
+ /// spelling of the filename, but is also expected to handle the case when
+ /// this method decides to use a different buffer.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,
+ const char *&BufStart, const char *&BufEnd);
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// for system #include's or not (i.e. using <> instead of "").
+ const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
+ bool isAngled, const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir);
+
+ /// GetCurLookup - The DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
+ /// implement #include_next and find directory-specific properties.
+ const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
+
+ /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+ /// #include.
+ bool isInPrimaryFile() const;
+
+ /// ConcatenateIncludeName - Handle cases where the #include name is expanded
+ /// from a macro as multiple tokens, which need to be glued together. This
+ /// occurs for code like:
+ /// #define FOO <a/b.h>
+ /// #include FOO
+ /// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
+ ///
+ /// This code concatenates and consumes tokens up to the '>' token. It returns
+ /// false if the > was found, otherwise it returns true if it finds and consumes
+ /// the EOM marker.
+ bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer);
+
private:
void PushIncludeMacroStack() {
@@ -646,10 +690,6 @@ private:
/// be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
- /// isInPrimaryFile - Return true if we're in the top-level file, not in a
- /// #include.
- bool isInPrimaryFile() const;
-
/// ReadMacroName - Lex and validate a macro name, which occurs after a
/// #define or #undef. This emits a diagnostic, sets the token kind to eom,
/// and discards the rest of the macro line if the macro name is invalid.
@@ -722,24 +762,6 @@ private:
/// start getting tokens from it using the PTH cache.
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
- /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
- /// checked and spelled filename, e.g. as an operand of #include. This returns
- /// true if the input filename was in <>'s or false if it were in ""'s. The
- /// caller is expected to provide a buffer that is large enough to hold the
- /// spelling of the filename, but is also expected to handle the case when
- /// this method decides to use a different buffer.
- bool GetIncludeFilenameSpelling(SourceLocation Loc,
- const char *&BufStart, const char *&BufEnd);
-
- /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
- /// return null on failure. isAngled indicates whether the file reference is
- /// for system #include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
- bool isAngled, const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir);
-
-
-
/// IsFileLexer - Returns true if we are lexing from a file and not a
/// pragma or a macro.
static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 8acdb30cc705..8d910959b9fa 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -17,6 +17,7 @@
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/OperatorKinds.h"
#include <cstdlib>
namespace clang {
@@ -62,12 +63,12 @@ class Token {
/// Kind - The actual flavor of token this is.
///
- unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind';
+ unsigned char Kind; // DON'T make Kind a 'tok::TokenKind';
// MSVC will treat it as a signed char and
// TokenKinds > 127 won't be handled correctly.
/// Flags - Bits we track about this token, members of the TokenFlags enum.
- unsigned Flags : 8;
+ unsigned char Flags;
public:
// Various flags set per token:
@@ -261,6 +262,9 @@ struct TemplateIdAnnotation {
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
+ /// FIXME: Temporarily stores the overloaded operator kind.
+ OverloadedOperatorKind Operator;
+
/// The declaration of the template corresponding to the
/// template-name. This is an Action::DeclTy*.
void *Template;
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 050b3f42e4cd..073365dcede3 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -161,6 +161,23 @@ public:
// Declaration Tracking Callbacks.
//===--------------------------------------------------------------------===//
+ typedef uintptr_t ParsingDeclStackState;
+
+ /// PushParsingDeclaration - Notes that the parser has begun
+ /// processing a declaration of some sort. Guaranteed to be matched
+ /// by a call to PopParsingDeclaration with the value returned by
+ /// this method.
+ virtual ParsingDeclStackState PushParsingDeclaration() {
+ return ParsingDeclStackState();
+ }
+
+ /// PopParsingDeclaration - Notes that the parser has completed
+ /// processing a declaration of some sort. The decl will be empty
+ /// if the declaration didn't correspond to a full declaration (or
+ /// if the actions module returned an empty decl for it).
+ virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) {
+ }
+
/// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
/// needs a decl group, it calls this to convert between the two
/// representations.
@@ -236,30 +253,36 @@ public:
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
- /// \brief Determine whether the given identifier refers to the name of a
+ /// \brief Determine whether the given name refers to a template.
+ ///
+ /// This callback is used by the parser after it has seen a '<' to determine
+ /// whether the given name refers to a template and, if so, what kind of
/// template.
///
- /// \param S the scope in which name lookup occurs
+ /// \param S the scope in which the name occurs.
///
- /// \param II the identifier that we are querying to determine whether it
- /// is a template.
+ /// \param SS the C++ nested-name-specifier that precedes the template name,
+ /// if any.
///
- /// \param IdLoc the source location of the identifier
+ /// \param Name the name that we are querying to determine whether it is
+ /// a template.
///
- /// \param SS the C++ scope specifier that precedes the template name, if
- /// any.
+ /// \param ObjectType if we are determining whether the given name is a
+ /// template name in the context of a member access expression (e.g.,
+ /// \c p->X<int>), this is the type of the object referred to by the
+ /// member access (e.g., \c p).
///
/// \param EnteringContext whether we are potentially entering the context
- /// referred to by the scope specifier \p SS
+ /// referred to by the nested-name-specifier \p SS, which allows semantic
+ /// analysis to look into uninstantiated templates.
///
/// \param Template if the name does refer to a template, the declaration
/// of the template that the name refers to.
///
/// \returns the kind of template that this name refers to.
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template) = 0;
@@ -854,47 +877,33 @@ public:
virtual SourceRange getExprRange(ExprTy *E) const {
return SourceRange();
}
-
- /// ActOnIdentifierExpr - Parse an identifier in expression context.
- /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
- /// token immediately after it.
- /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
- /// namespace) that the identifier must be a member of.
- /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
- virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS = 0,
- bool isAddressOfOperand = false){
- return ExprEmpty();
- }
-
- /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
- /// name (e.g., @c operator+ ) as an expression. This is very
- /// similar to ActOnIdentifierExpr, except that instead of providing
- /// an identifier the parser provides the kind of overloaded
- /// operator that was parsed.
- virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
- Scope *S, SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen, const CXXScopeSpec &SS,
- bool isAddressOfOperand = false) {
- return ExprEmpty();
- }
-
- /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
- /// name (e.g., @c operator void const *) as an expression. This is
- /// very similar to ActOnIdentifierExpr, except that instead of
- /// providing an identifier the parser provides the type of the
- /// conversion function.
- virtual OwningExprResult ActOnCXXConversionFunctionExpr(
- Scope *S, SourceLocation OperatorLoc,
- TypeTy *Type, bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand = false) {
+
+ /// \brief Parsed an id-expression (C++) or identifier (C) in expression
+ /// context, e.g., the expression "x" that refers to a variable named "x".
+ ///
+ /// \param S the scope in which this id-expression or identifier occurs.
+ ///
+ /// \param SS the C++ nested-name-specifier that qualifies the name of the
+ /// value, e.g., "std::" in "std::sort".
+ ///
+ /// \param Name the name to which the id-expression refers. In C, this will
+ /// always be an identifier. In C++, it may also be an overloaded operator,
+ /// destructor name (if there is a nested-name-specifier), or template-id.
+ ///
+ /// \param HasTrailingLParen whether the next token following the
+ /// id-expression or identifier is a left parentheses ('(').
+ ///
+ /// \param IsAddressOfOperand whether the token that precedes this
+ /// id-expression or identifier was an ampersand ('&'), indicating that
+ /// we will be taking the address of this expression.
+ virtual OwningExprResult ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand) {
return ExprEmpty();
}
-
+
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
return ExprEmpty();
@@ -936,16 +945,42 @@ public:
SourceLocation RLoc) {
return ExprEmpty();
}
- virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ObjCImpDecl,
- const CXXScopeSpec *SS = 0) {
+
+ /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
+ /// of the form \c x.m or \c p->m.
+ ///
+ /// \param S the scope in which the member access expression occurs.
+ ///
+ /// \param Base the class or pointer to class into which this member
+ /// access expression refers, e.g., \c x in \c x.m.
+ ///
+ /// \param OpLoc the location of the "." or "->" operator.
+ ///
+ /// \param OpKind the kind of member access operator, which will be either
+ /// tok::arrow ("->") or tok::period (".").
+ ///
+ /// \param SS in C++, the nested-name-specifier that precedes the member
+ /// name, if any.
+ ///
+ /// \param Member the name of the member that we are referring to. In C,
+ /// this will always store an identifier; in C++, we may also have operator
+ /// names, conversion function names, destructors, and template names.
+ ///
+ /// \param ObjCImpDecl the Objective-C implementation declaration.
+ /// FIXME: Do we really need this?
+ ///
+ /// \param HasTrailingLParen whether this member name is immediately followed
+ /// by a left parentheses ('(').
+ virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen) {
return ExprEmpty();
}
-
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations. There are guaranteed to be one fewer commas than arguments,
@@ -1245,8 +1280,7 @@ public:
}
/// ActOnFriendTypeDecl - Parsed a friend type declaration.
- virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS,
+ virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TParams) {
return DeclPtrTy();
}
@@ -1376,123 +1410,6 @@ public:
return ExprEmpty();
}
- /// ActOnDestructorReferenceExpr - Parsed a destructor reference, for example:
- ///
- /// t->~T();
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a C++ destructor reference that refers to a type.
- ///
- /// This action is used when parsing a destructor reference that uses a
- /// template-id, e.g.,
- ///
- /// \code
- /// t->~Tmpl<T1, T2>
- /// \endcode
- ///
- /// \param S the scope in which the destructor reference occurs.
- /// \param Base the base object of the destructor reference expression.
- /// \param OpLoc the location of the operator ('.' or '->').
- /// \param OpKind the kind of the destructor reference operator ('.' or '->').
- /// \param TypeRange the source range that covers the destructor type.
- /// \param Type the type that is being destroyed.
- /// \param SS the scope specifier that precedes the destructor name.
- /// \param HasTrailingLParen whether the destructor name is followed by a '('.
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *Type,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
- /// reference, for example:
- ///
- /// t.operator++();
- virtual OwningExprResult
- ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS = 0) {
- return ExprEmpty();
- }
-
- /// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion
- /// function reference, for example:
- ///
- /// t.operator int();
- virtual OwningExprResult
- ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS = 0) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a reference to a member template-id.
- ///
- /// This callback will occur instead of ActOnMemberReferenceExpr() when the
- /// member in question is a template for which the code provides an
- /// explicitly-specified template argument list, e.g.,
- ///
- /// \code
- /// x.f<int>()
- /// \endcode
- ///
- /// \param S the scope in which the member reference expression occurs
- ///
- /// \param Base the expression to the left of the "." or "->".
- ///
- /// \param OpLoc the location of the "." or "->".
- ///
- /// \param OpKind the kind of operator, which will be "." or "->".
- ///
- /// \param SS the scope specifier that precedes the template-id in, e.g.,
- /// \c x.Base::f<int>().
- ///
- /// \param Template the declaration of the template that is being referenced.
- ///
- /// \param TemplateNameLoc the location of the template name referred to by
- /// \p Template.
- ///
- /// \param LAngleLoc the location of the left angle bracket ('<')
- ///
- /// \param TemplateArgs the (possibly-empty) template argument list provided
- /// as part of the member reference.
- ///
- /// \param RAngleLoc the location of the right angle bracket ('>')
- virtual OwningExprResult
- ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- // FIXME: "template" keyword?
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- return ExprEmpty();
- }
-
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
/// (C++ [intro.execution]p12).
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
@@ -1712,40 +1629,6 @@ public:
return TypeResult();
}
- /// \brief Form a reference to a template-id (that will refer to a function)
- /// from a template and a list of template arguments.
- ///
- /// This action forms an expression that references the given template-id,
- /// possibly checking well-formedness of the template arguments. It does not
- /// imply the declaration of any entity.
- ///
- /// \param SS The scope specifier that may precede the template name.
- ///
- /// \param Template A template whose specialization results in a
- /// function or a dependent template.
- ///
- /// \param TemplateNameLoc The location of the template name.
- ///
- /// \param LAngleLoc The location of the left angle bracket ('<') that starts
- /// the template argument list.
- ///
- /// \param TemplateArgs The template arguments in the template argument list,
- /// which may be empty.
- ///
- /// \param TemplateArgLocs The locations of the template arguments.
- ///
- /// \param RAngleLoc The location of the right angle bracket ('>') that
- /// closes the template argument list.
- virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- return ExprError();
- }
-
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
@@ -1756,22 +1639,19 @@ public:
///
/// \param TemplateKWLoc the location of the "template" keyword (if any).
///
- /// \param Name the name of the template (an identifier)
- ///
- /// \param NameLoc the location of the identifier
- ///
/// \param SS the nested-name-specifier that precedes the "template" keyword
- /// or the template name. FIXME: If the dependent template name occurs in
+ /// or the template name. If the dependent template name occurs in
/// a member access expression, e.g., "x.template f<T>", this
/// nested-name-specifier will be empty.
///
+ /// \param Name the name of the template.
+ ///
/// \param ObjectType if this dependent template name occurs in the
/// context of a member access expression, the type of the object being
/// accessed.
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType) {
return TemplateTy();
}
@@ -2473,13 +2353,12 @@ public:
const CXXScopeSpec *SS);
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template);
-
+
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 51970f1867d9..dccb8bcfeb9a 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -390,17 +390,20 @@ public:
};
- ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
- GetterName(0), SetterName(0) { }
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
+ GetterName(0), SetterName(0) { }
ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
- void setObjCDeclQualifier(ObjCDeclQualifier DQVal)
- { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
+ }
- ObjCPropertyAttributeKind getPropertyAttributes() const
- { return ObjCPropertyAttributeKind(PropertyAttributes); }
+ ObjCPropertyAttributeKind getPropertyAttributes() const {
+ return ObjCPropertyAttributeKind(PropertyAttributes);
+ }
void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
PropertyAttributes =
- (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
+ (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
}
const IdentifierInfo *getGetterName() const { return GetterName; }
@@ -456,6 +459,193 @@ public:
}
};
+/// \brief Represents a C++ unqualified-id that has been parsed.
+class UnqualifiedId {
+private:
+ const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT
+
+public:
+ /// \brief Describes the kind of unqualified-id parsed.
+ enum IdKind {
+ /// \brief An identifier.
+ IK_Identifier,
+ /// \brief An overloaded operator name, e.g., operator+.
+ IK_OperatorFunctionId,
+ /// \brief A conversion function name, e.g., operator int.
+ IK_ConversionFunctionId,
+ /// \brief A constructor name.
+ IK_ConstructorName,
+ /// \brief A destructor name.
+ IK_DestructorName,
+ /// \brief A template-id, e.g., f<int>.
+ IK_TemplateId
+ } Kind;
+
+ /// \brief Anonymous union that holds extra data associated with the
+ /// parsed unqualified-id.
+ union {
+ /// \brief When Kind == IK_Identifier, the parsed identifier.
+ IdentifierInfo *Identifier;
+
+ /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
+ /// that we parsed.
+ struct {
+ /// \brief The kind of overloaded operator.
+ OverloadedOperatorKind Operator;
+
+ /// \brief The source locations of the individual tokens that name
+ /// the operator, e.g., the "new", "[", and "]" tokens in
+ /// operator new [].
+ ///
+ /// Different operators have different numbers of tokens in their name,
+ /// up to three. Any remaining source locations in this array will be
+ /// set to an invalid value for operators with fewer than three tokens.
+ unsigned SymbolLocations[3];
+ } OperatorFunctionId;
+
+ /// \brief When Kind == IK_ConversionFunctionId, the type that the
+ /// conversion function names.
+ ActionBase::TypeTy *ConversionFunctionId;
+
+ /// \brief When Kind == IK_ConstructorName, the class-name of the type
+ /// whose constructor is being referenced.
+ ActionBase::TypeTy *ConstructorName;
+
+ /// \brief When Kind == IK_DestructorName, the type referred to by the
+ /// class-name.
+ ActionBase::TypeTy *DestructorName;
+
+ /// \brief When Kind == IK_TemplateId, the template-id annotation that
+ /// contains the template name and template arguments.
+ TemplateIdAnnotation *TemplateId;
+ };
+
+ /// \brief The location of the first token that describes this unqualified-id,
+ /// which will be the location of the identifier, "operator" keyword,
+ /// tilde (for a destructor), or the template name of a template-id.
+ SourceLocation StartLocation;
+
+ /// \brief The location of the last token that describes this unqualified-id.
+ SourceLocation EndLocation;
+
+ UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
+
+ /// \brief Do not use this copy constructor. It is temporary, and only
+ /// exists because we are holding FieldDeclarators in a SmallVector when we
+ /// don't actually need them.
+ ///
+ /// FIXME: Kill this copy constructor.
+ UnqualifiedId(const UnqualifiedId &Other)
+ : Kind(IK_Identifier), Identifier(Other.Identifier),
+ StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) {
+ assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
+ }
+
+ /// \brief Destroy this unqualified-id.
+ ~UnqualifiedId() { clear(); }
+
+ /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ /// state.
+ void clear();
+
+ /// \brief Determine whether this unqualified-id refers to a valid name.
+ bool isValid() const { return StartLocation.isValid(); }
+
+ /// \brief Determine whether this unqualified-id refers to an invalid name.
+ bool isInvalid() const { return !isValid(); }
+
+ /// \brief Determine what kind of name we have.
+ IdKind getKind() const { return Kind; }
+
+ /// \brief Specify that this unqualified-id was parsed as an identifier.
+ ///
+ /// \param Id the parsed identifier.
+ /// \param IdLoc the location of the parsed identifier.
+ void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
+ Kind = IK_Identifier;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = EndLocation = IdLoc;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as an
+ /// operator-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Op the overloaded operator.
+ ///
+ /// \param SymbolLocations the locations of the individual operator symbols
+ /// in the operator.
+ void setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]);
+
+ /// \brief Specify that this unqualified-id was parsed as a
+ /// conversion-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Ty the type to which this conversion function is converting.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConversionFunctionId(SourceLocation OperatorLoc,
+ ActionBase::TypeTy *Ty,
+ SourceLocation EndLoc) {
+ Kind = IK_ConversionFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = EndLoc;
+ ConversionFunctionId = Ty;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a constructor name.
+ ///
+ /// \param ClassType the class type referred to by the constructor name.
+ ///
+ /// \param ClassNameLoc the location of the class name.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConstructorName(ActionBase::TypeTy *ClassType,
+ SourceLocation ClassNameLoc,
+ SourceLocation EndLoc) {
+ Kind = IK_ConstructorName;
+ StartLocation = ClassNameLoc;
+ EndLocation = EndLoc;
+ ConstructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a destructor name.
+ ///
+ /// \param TildeLoc the location of the '~' that introduces the destructor
+ /// name.
+ ///
+ /// \param ClassType the name of the class referred to by the destructor name.
+ void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
+ SourceLocation EndLoc) {
+ Kind = IK_DestructorName;
+ StartLocation = TildeLoc;
+ EndLocation = EndLoc;
+ DestructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a template-id.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_TemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+ }
+
+ /// \brief Return the source range that covers this unqualified-id.
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLocation, EndLocation);
+ }
+};
+
/// CachedTokens - A set of tokens that has been cached for later
/// parsing.
typedef llvm::SmallVector<Token, 4> CachedTokens;
@@ -790,33 +980,16 @@ public:
BlockLiteralContext // Block literal declarator.
};
- /// DeclaratorKind - The kind of declarator this represents.
- enum DeclaratorKind {
- DK_Abstract, // An abstract declarator (has no identifier)
- DK_Normal, // A normal declarator (has an identifier).
- DK_Constructor, // A C++ constructor (identifier is the class name)
- DK_Destructor, // A C++ destructor (identifier is ~class name)
- DK_Operator, // A C++ overloaded operator name
- DK_Conversion, // A C++ conversion function (identifier is
- // "operator " then the type name)
- DK_TemplateId // A C++ template-id naming a function template
- // specialization.
- };
-
private:
const DeclSpec &DS;
CXXScopeSpec SS;
- IdentifierInfo *Identifier;
- SourceLocation IdentifierLoc;
+ UnqualifiedId Name;
SourceRange Range;
/// Context - Where we are parsing this declarator.
///
TheContext Context;
- /// Kind - What kind of declarator this is.
- DeclaratorKind Kind;
-
/// DeclTypeInfo - This holds each type that the declarator includes as it is
/// parsed. This is pushed from the identifier out, which means that element
/// #0 will be the most closely bound to the identifier, and
@@ -835,21 +1008,6 @@ private:
/// AsmLabel - The asm label, if specified.
ActionBase::ExprTy *AsmLabel;
- union {
- // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
- // type associated with the constructor, destructor, or conversion
- // operator.
- ActionBase::TypeTy *Type;
-
- /// When Kind is DK_Operator, this is the actual overloaded
- /// operator that this declarator names.
- OverloadedOperatorKind OperatorKind;
-
- /// When Kind is DK_TemplateId, this is the template-id annotation that
- /// contains the template and its template arguments.
- TemplateIdAnnotation *TemplateId;
- };
-
/// InlineParams - This is a local array used for the first function decl
/// chunk to avoid going to the heap for the common case when we have one
/// function chunk in the declarator.
@@ -863,10 +1021,9 @@ private:
public:
Declarator(const DeclSpec &ds, TheContext C)
- : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C),
- Kind(DK_Abstract),
+ : DS(ds), Range(ds.getSourceRange()), Context(C),
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
- GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
+ GroupingParens(false), AttrList(0), AsmLabel(0),
InlineParamsUsed(false), Extension(false) {
}
@@ -890,8 +1047,10 @@ public:
const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
CXXScopeSpec &getCXXScopeSpec() { return SS; }
+ /// \brief Retrieve the name specified by this declarator.
+ UnqualifiedId &getName() { return Name; }
+
TheContext getContext() const { return Context; }
- DeclaratorKind getKind() const { return Kind; }
/// getSourceRange - Get the source range that spans this declarator.
const SourceRange &getSourceRange() const { return Range; }
@@ -922,22 +1081,15 @@ public:
/// clear - Reset the contents of this Declarator.
void clear() {
SS.clear();
- Identifier = 0;
- IdentifierLoc = SourceLocation();
+ Name.clear();
Range = DS.getSourceRange();
- if (Kind == DK_TemplateId)
- TemplateId->Destroy();
-
- Kind = DK_Abstract;
-
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
DeclTypeInfo[i].destroy();
DeclTypeInfo.clear();
delete AttrList;
AttrList = 0;
AsmLabel = 0;
- Type = 0;
InlineParamsUsed = false;
}
@@ -968,84 +1120,28 @@ public:
/// isPastIdentifier - Return true if we have parsed beyond the point where
/// the
- bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
+ bool isPastIdentifier() const { return Name.isValid(); }
/// hasName - Whether this declarator has a name, which might be an
/// identifier (accessible via getIdentifier()) or some kind of
/// special C++ name (constructor, destructor, etc.).
- bool hasName() const { return getKind() != DK_Abstract; }
-
- IdentifierInfo *getIdentifier() const { return Identifier; }
- SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
-
- void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
- Identifier = ID;
- IdentifierLoc = Loc;
- if (ID)
- Kind = DK_Normal;
- else
- Kind = DK_Abstract;
- SetRangeEnd(Loc);
- }
-
- /// setConstructor - Set this declarator to be a C++ constructor
- /// declarator. Also extends the range.
- void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) {
- IdentifierLoc = Loc;
- Kind = DK_Constructor;
- Type = Ty;
- SetRangeEnd(Loc);
- }
-
- /// setDestructor - Set this declarator to be a C++ destructor
- /// declarator. Also extends the range to End, which should be the identifier
- /// token.
- void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc,
- SourceLocation EndLoc) {
- IdentifierLoc = Loc;
- Kind = DK_Destructor;
- Type = Ty;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
- }
-
- /// setConversionFunction - Set this declarator to be a C++
- /// conversion function declarator (e.g., @c operator int const *).
- /// Also extends the range to EndLoc, which should be the last token of the
- /// type name.
- void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc,
- SourceLocation EndLoc) {
- Identifier = 0;
- IdentifierLoc = Loc;
- Kind = DK_Conversion;
- Type = Ty;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
+ bool hasName() const {
+ return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
}
- /// setOverloadedOperator - Set this declaration to be a C++
- /// overloaded operator declarator (e.g., @c operator+).
- /// Also extends the range to EndLoc, which should be the last token of the
- /// operator.
- void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc,
- SourceLocation EndLoc) {
- IdentifierLoc = Loc;
- Kind = DK_Operator;
- OperatorKind = Op;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
+ IdentifierInfo *getIdentifier() const {
+ if (Name.getKind() == UnqualifiedId::IK_Identifier)
+ return Name.Identifier;
+
+ return 0;
}
+ SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
- /// \brief Set this declaration to be a C++ template-id, which includes the
- /// template (or set of function templates) along with template arguments.
- void setTemplateId(TemplateIdAnnotation *TemplateId) {
- assert(TemplateId && "NULL template-id provided to declarator?");
- IdentifierLoc = TemplateId->TemplateNameLoc;
- Kind = DK_TemplateId;
- SetRangeEnd(TemplateId->RAngleLoc);
- this->TemplateId = TemplateId;
+ /// \brief Set the name of this declarator to be the given identifier.
+ void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+ Name.setIdentifier(Id, IdLoc);
}
-
+
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk.
void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
@@ -1069,6 +1165,13 @@ public:
return DeclTypeInfo[i];
}
+ void DropFirstTypeObject()
+ {
+ assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
+ DeclTypeInfo.front().destroy();
+ DeclTypeInfo.erase(DeclTypeInfo.begin());
+ }
+
/// isFunctionDeclarator - Once this declarator is fully parsed and formed,
/// this method returns true if the identifier is a function declarator.
bool isFunctionDeclarator() const {
@@ -1108,22 +1211,6 @@ public:
void setExtension(bool Val = true) { Extension = Val; }
bool getExtension() const { return Extension; }
- ActionBase::TypeTy *getDeclaratorIdType() const {
- assert((Kind == DK_Constructor || Kind == DK_Destructor ||
- Kind == DK_Conversion) && "Declarator kind does not have a type");
- return Type;
- }
-
- OverloadedOperatorKind getOverloadedOperator() const {
- assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
- return OperatorKind;
- }
-
- TemplateIdAnnotation *getTemplateId() {
- assert(Kind == DK_TemplateId && "Declarator is not a template-id");
- return TemplateId;
- }
-
void setInvalidType(bool Val = true) { InvalidType = Val; }
bool isInvalidType() const {
return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
@@ -1142,7 +1229,7 @@ struct FieldDeclarator {
BitfieldSize = 0;
}
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 9cb4677f6637..f34d469d9823 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -571,6 +571,99 @@ private:
return *ClassStack.top();
}
+ /// \brief RAII object used to inform the actions that we're
+ /// currently parsing a declaration. This is active when parsing a
+ /// variable's initializer, but not when parsing the body of a
+ /// class or function definition.
+ class ParsingDeclRAIIObject {
+ Action &Actions;
+ Action::ParsingDeclStackState State;
+ bool Popped;
+
+ public:
+ ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
+ push();
+ }
+
+ ~ParsingDeclRAIIObject() {
+ abort();
+ }
+
+ /// Resets the RAII object for a new declaration.
+ void reset() {
+ abort();
+ push();
+ }
+
+ /// Signals that the context was completed without an appropriate
+ /// declaration being parsed.
+ void abort() {
+ pop(DeclPtrTy());
+ }
+
+ void complete(DeclPtrTy D) {
+ assert(!Popped && "ParsingDeclaration has already been popped!");
+ pop(D);
+ }
+
+ private:
+ void push() {
+ State = Actions.PushParsingDeclaration();
+ Popped = false;
+ }
+
+ void pop(DeclPtrTy D) {
+ if (!Popped) {
+ Actions.PopParsingDeclaration(State, D);
+ Popped = true;
+ }
+ }
+ };
+
+ /// A class for parsing a DeclSpec.
+ class ParsingDeclSpec : public DeclSpec {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
+ }
+
+ void complete(DeclPtrTy D) {
+ ParsingRAII.complete(D);
+ }
+
+ void abort() {
+ ParsingRAII.abort();
+ }
+ };
+
+ /// A class for parsing a declarator.
+ class ParsingDeclarator : public Declarator {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+ : Declarator(DS, C), ParsingRAII(P) {
+ }
+
+ const ParsingDeclSpec &getDeclSpec() const {
+ return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+ }
+
+ ParsingDeclSpec &getMutableDeclSpec() const {
+ return const_cast<ParsingDeclSpec&>(getDeclSpec());
+ }
+
+ void clear() {
+ Declarator::clear();
+ ParsingRAII.reset();
+ }
+
+ void complete(DeclPtrTy D) {
+ ParsingRAII.complete(D);
+ }
+ };
+
/// \brief RAII object used to
class ParsingClassDefinition {
Parser &P;
@@ -603,14 +696,17 @@ private:
: Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
- bool isSpecialization)
+ bool isSpecialization,
+ bool lastParameterListWasEmpty = false)
: Kind(isSpecialization? ExplicitSpecialization : Template),
- TemplateParams(TemplateParams) { }
+ TemplateParams(TemplateParams),
+ LastParameterListWasEmpty(lastParameterListWasEmpty) { }
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
SourceLocation TemplateLoc)
: Kind(ExplicitInstantiation), TemplateParams(0),
- ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
+ ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+ LastParameterListWasEmpty(false){ }
/// \brief The kind of template we are parsing.
enum {
@@ -635,6 +731,9 @@ private:
/// \brief The location of the 'template' keyword, for an explicit
/// instantiation.
SourceLocation TemplateLoc;
+
+ /// \brief Whether the last template parameter list was empty.
+ bool LastParameterListWasEmpty;
};
void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
@@ -658,7 +757,7 @@ private:
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseFunctionDefinition(Declarator &D,
+ DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
void ParseKNRParamDeclarations(Declarator &D);
// EndLoc, if non-NULL, is filled with the location of the last token of
@@ -944,11 +1043,12 @@ private:
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi = true);
+ SourceLocation &DeclEnd);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd = 0);
DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
@@ -973,8 +1073,16 @@ private:
void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl);
- void ParseStructDeclaration(DeclSpec &DS,
- llvm::SmallVectorImpl<FieldDeclarator> &Fields);
+
+ struct FieldCallback {
+ virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
+ virtual ~FieldCallback() {}
+
+ private:
+ virtual void _anchor();
+ };
+
+ void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
bool isDeclarationSpecifier();
bool isTypeSpecifierQualifier();
@@ -1197,6 +1305,21 @@ private:
BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;
+ bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Id);
+ bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result);
+ bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result);
+
//===--------------------------------------------------------------------===//
// C++ 13.5: Overloaded operators [over.oper]
// EndLoc, if non-NULL, is filled with the location of the last token of
@@ -1247,6 +1370,7 @@ private:
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
SourceLocation TemplateKWLoc = SourceLocation(),
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index d2f509df7b2c..5b3522c9eb49 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -26,6 +26,7 @@ namespace clang {
class FunctionDecl;
class FunctionType;
class FunctionTemplateDecl;
+class IdentifierInfo;
class NamedDecl;
class NestedNameSpecifier;
class Sema;
@@ -150,7 +151,8 @@ public:
/// \brief Describes the kind of result generated.
enum ResultKind {
RK_Declaration = 0, //< Refers to a declaration
- RK_Keyword //< Refers to a keyword or symbol.
+ RK_Keyword, //< Refers to a keyword or symbol.
+ RK_Macro //< Refers to a macro
};
/// \brief The kind of result stored here.
@@ -164,6 +166,9 @@ public:
/// \brief When Kind == RK_Keyword, the string representing the keyword
/// or symbol's spelling.
const char *Keyword;
+
+ /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ IdentifierInfo *Macro;
};
/// \brief Describes how good this result is, with zero being the best
@@ -199,6 +204,12 @@ public:
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
Qualifier(0) { }
+ /// \brief Build a result that refers to a macro.
+ Result(IdentifierInfo *Macro, unsigned Rank)
+ : Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ Qualifier(0) { }
+
/// \brief Retrieve the declaration stored in this result.
NamedDecl *getDeclaration() const {
assert(Kind == RK_Declaration && "Not a declaration result");
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7f5fa35842af..aef3d2989415 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -22,9 +22,10 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include "RecordLayoutBuilder.h"
using namespace clang;
@@ -138,9 +139,9 @@ void ASTContext::PrintStats() const {
}
-void ASTContext::InitBuiltinType(QualType &R, BuiltinType::Kind K) {
+void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
- R = QualType(Ty, 0);
+ R = CanQualType::CreateUnsafe(QualType(Ty, 0));
Types.push_back(Ty);
}
@@ -872,6 +873,55 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
}
}
+/// CollectInheritedProtocols - Collect all protocols in current class and
+/// those inherited by it.
+void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols) {
+ if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
+ PE = OI->protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.push_back(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P)
+ CollectInheritedProtocols(*P, Protocols);
+ }
+
+ // Categories of this Interface.
+ for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList();
+ CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
+ CollectInheritedProtocols(CDeclChain, Protocols);
+ if (ObjCInterfaceDecl *SD = OI->getSuperClass())
+ while (SD) {
+ CollectInheritedProtocols(SD, Protocols);
+ SD = SD->getSuperClass();
+ }
+ return;
+ }
+ if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+ PE = OC->protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.push_back(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P)
+ CollectInheritedProtocols(*P, Protocols);
+ }
+ return;
+ }
+ if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
+ PE = OP->protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.push_back(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P)
+ CollectInheritedProtocols(*P, Protocols);
+ }
+ return;
+ }
+}
+
unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
unsigned count = 0;
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
@@ -955,6 +1005,13 @@ DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
return DInfo;
}
+DeclaratorInfo *ASTContext::getTrivialDeclaratorInfo(QualType T,
+ SourceLocation L) {
+ DeclaratorInfo *DI = CreateDeclaratorInfo(T);
+ DI->getTypeLoc().initialize(L);
+ return DI;
+}
+
/// getInterfaceLayoutImpl - Get or compute information about the
/// layout of the given interface.
///
@@ -1757,6 +1814,19 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ QualType Canon) {
+ llvm::SmallVector<TemplateArgument, 4> ArgVec;
+ ArgVec.reserve(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ArgVec.push_back(Args[i].getArgument());
+
+ return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, Canon);
+}
+
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgument *Args,
unsigned NumArgs,
QualType Canon) {
@@ -2235,7 +2305,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
DSAT->getIndexTypeCVRQualifiers(),
- DSAT->getBracketsRange()));
+ DSAT->getBracketsRange())->getCanonicalTypeInternal());
VariableArrayType *VAT = cast<VariableArrayType>(AT);
return CanQualType::CreateUnsafe(getVariableArrayType(NewEltTy,
@@ -2290,17 +2360,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
return Arg;
case TemplateArgument::Declaration:
- return TemplateArgument(SourceLocation(),
- Arg.getAsDecl()->getCanonicalDecl());
+ return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
case TemplateArgument::Integral:
- return TemplateArgument(SourceLocation(),
- *Arg.getAsIntegral(),
+ return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));
case TemplateArgument::Type:
- return TemplateArgument(SourceLocation(),
- getCanonicalType(Arg.getAsType()));
+ return TemplateArgument(getCanonicalType(Arg.getAsType()));
case TemplateArgument::Pack: {
// FIXME: Allocate in ASTContext
@@ -2847,12 +2914,13 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
bool HasCopyAndDispose = BlockRequiresCopying(Ty);
// FIXME: Move up
- static int UniqueBlockByRefTypeID = 0;
- char Name[36];
- sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName);
+ static unsigned int UniqueBlockByRefTypeID = 0;
+ llvm::SmallString<36> Name;
+ llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
+ ++UniqueBlockByRefTypeID << '_' << DeclName;
RecordDecl *T;
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get(Name));
+ &Idents.get(Name.str()));
T->startDefinition();
QualType Int32Ty = IntTy;
assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
@@ -2896,12 +2964,13 @@ QualType ASTContext::getBlockParmType(
bool BlockHasCopyDispose,
llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
// FIXME: Move up
- static int UniqueBlockParmTypeID = 0;
- char Name[36];
- sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID);
+ static unsigned int UniqueBlockParmTypeID = 0;
+ llvm::SmallString<36> Name;
+ llvm::raw_svector_ostream(Name) << "__block_literal_"
+ << ++UniqueBlockParmTypeID;
RecordDecl *T;
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get(Name));
+ &Idents.get(Name.str()));
QualType FieldTypes[] = {
getPointerType(VoidPtrTy),
IntTy,
@@ -3409,7 +3478,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- if (OPT->isObjCClassType()) {
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ // FIXME: Consider if we need to output qualifiers for 'Class<p>'.
+ // Since this is a binary compatibility issue, need to consult with runtime
+ // folks. Fortunately, this is a *very* obsure construct.
S += '#';
return;
}
@@ -3447,9 +3519,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
S += '@';
- if (FD || EncodingProperty) {
+ if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) {
S += '"';
- S += OPT->getInterfaceDecl()->getNameAsCString();
+ S += OPT->getInterfaceDecl()->getIdentifier()->getName();
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
E = OPT->qual_end(); I != E; ++I) {
S += '<';
@@ -3590,12 +3662,42 @@ TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
return TemplateName(QTN);
}
+/// \brief Retrieve the template name that represents a dependent
+/// template name such as \c MetaFun::template operator+.
+TemplateName
+ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator) {
+ assert((!NNS || NNS->isDependent()) &&
+ "Nested name specifier must be dependent");
+
+ llvm::FoldingSetNodeID ID;
+ DependentTemplateName::Profile(ID, NNS, Operator);
+
+ void *InsertPos = 0;
+ DependentTemplateName *QTN =
+ DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (QTN)
+ return TemplateName(QTN);
+
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ if (CanonNNS == NNS) {
+ QTN = new (*this,4) DependentTemplateName(NNS, Operator);
+ } else {
+ TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
+ QTN = new (*this,4) DependentTemplateName(NNS, Operator, Canon);
+ }
+
+ DependentTemplateNames.InsertNode(QTN, InsertPos);
+ return TemplateName(QTN);
+}
+
/// getFromTargetType - Given one of the integer types provided by
/// TargetInfo, produce the corresponding type. The unsigned @p Type
/// is actually a value of type @c TargetInfo::IntType.
-QualType ASTContext::getFromTargetType(unsigned Type) const {
+CanQualType ASTContext::getFromTargetType(unsigned Type) const {
switch (Type) {
- case TargetInfo::NoInt: return QualType();
+ case TargetInfo::NoInt: return CanQualType();
case TargetInfo::SignedShort: return ShortTy;
case TargetInfo::UnsignedShort: return UnsignedShortTy;
case TargetInfo::SignedInt: return IntTy;
@@ -3607,7 +3709,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
}
assert(false && "Unhandled TargetInfo::IntType value");
- return QualType();
+ return CanQualType();
}
//===----------------------------------------------------------------------===//
@@ -3836,6 +3938,79 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
return false;
}
+/// getIntersectionOfProtocols - This routine finds the intersection of set
+/// of protocols inherited from two distinct objective-c pointer objects.
+/// It is used to build composite qualifier list of the composite type of
+/// the conditional expression involving two objective-c pointer objects.
+static
+void getIntersectionOfProtocols(ASTContext &Context,
+ const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT,
+ llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
+
+ const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+ const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
+ unsigned LHSNumProtocols = LHS->getNumProtocols();
+ if (LHSNumProtocols > 0)
+ InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
+ else {
+ llvm::SmallVector<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
+ Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols);
+ InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
+ LHSInheritedProtocols.end());
+ }
+
+ unsigned RHSNumProtocols = RHS->getNumProtocols();
+ if (RHSNumProtocols > 0) {
+ ObjCProtocolDecl **RHSProtocols = (ObjCProtocolDecl **)RHS->qual_begin();
+ for (unsigned i = 0; i < RHSNumProtocols; ++i)
+ if (InheritedProtocolSet.count(RHSProtocols[i]))
+ IntersectionOfProtocols.push_back(RHSProtocols[i]);
+ }
+ else {
+ llvm::SmallVector<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
+ Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols);
+ // FIXME. This may cause duplication of protocols in the list, but should
+ // be harmless.
+ for (unsigned i = 0, len = RHSInheritedProtocols.size(); i < len; ++i)
+ if (InheritedProtocolSet.count(RHSInheritedProtocols[i]))
+ IntersectionOfProtocols.push_back(RHSInheritedProtocols[i]);
+ }
+}
+
+/// areCommonBaseCompatible - Returns common base class of the two classes if
+/// one found. Note that this is O'2 algorithm. But it will be called as the
+/// last type comparison in a ?-exp of ObjC pointer types before a
+/// warning is issued. So, its invokation is extremely rare.
+QualType ASTContext::areCommonBaseCompatible(
+ const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT) {
+ const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+ const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+ if (!LHS || !RHS)
+ return QualType();
+
+ while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) {
+ QualType LHSTy = getObjCInterfaceType(LHSIDecl);
+ LHS = LHSTy->getAs<ObjCInterfaceType>();
+ if (canAssignObjCInterfaces(LHS, RHS)) {
+ llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols;
+ getIntersectionOfProtocols(*this,
+ LHSOPT, RHSOPT, IntersectionOfProtocols);
+ if (IntersectionOfProtocols.empty())
+ LHSTy = getObjCObjectPointerType(LHSTy);
+ else
+ LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0],
+ IntersectionOfProtocols.size());
+ return LHSTy;
+ }
+ }
+
+ return QualType();
+}
+
bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS) {
// Verify that the base decls are compatible: the RHS must be a subclass of
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 20e1150b22c2..e541406790a6 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangAST
StmtPrinter.cpp
StmtProfile.cpp
StmtViz.cpp
+ TemplateBase.cpp
TemplateName.cpp
Type.cpp
TypeLoc.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d270a958f0ae..a6996a4bfe5c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -91,13 +91,6 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg);
}
-QualType ParmVarDecl::getOriginalType() const {
- if (const OriginalParmVarDecl *PVD =
- dyn_cast<OriginalParmVarDecl>(this))
- return PVD->OriginalType;
- return getType();
-}
-
SourceRange ParmVarDecl::getDefaultArgRange() const {
if (const Expr *E = getInit())
return E->getSourceRange();
@@ -140,14 +133,6 @@ bool VarDecl::isExternC() const {
return false;
}
-OriginalParmVarDecl *OriginalParmVarDecl::Create(
- ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- QualType T, DeclaratorInfo *DInfo,
- QualType OT, StorageClass S, Expr *DefArg) {
- return new (C) OriginalParmVarDecl(DC, L, Id, T, DInfo, OT, S, DefArg);
-}
-
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName N, QualType T,
@@ -193,9 +178,9 @@ void EnumConstantDecl::Destroy(ASTContext& C) {
}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- IdentifierInfo *Id, QualType T) {
- return new (C) TypedefDecl(DC, L, Id, T);
+ SourceLocation L, IdentifierInfo *Id,
+ DeclaratorInfo *DInfo) {
+ return new (C) TypedefDecl(DC, L, Id, DInfo);
}
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
@@ -398,6 +383,19 @@ bool VarDecl::isOutOfLine() const {
return false;
}
+VarDecl *VarDecl::getOutOfLineDefinition() {
+ if (!isStaticDataMember())
+ return 0;
+
+ for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
+ RD != RDEnd; ++RD) {
+ if (RD->getLexicalDeclContext()->isFileContext())
+ return *RD;
+ }
+
+ return 0;
+}
+
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
@@ -644,7 +642,34 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
-/// \brief For an inline function definition in C, determine whether the
+bool FunctionDecl::isInlined() const {
+ if (isInlineSpecified() || (isa<CXXMethodDecl>(this) && !isOutOfLine()))
+ return true;
+
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ // Handle below.
+ break;
+ }
+
+ const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
+ Stmt *Pattern = 0;
+ if (PatternDecl)
+ Pattern = PatternDecl->getBody(PatternDecl);
+
+ if (Pattern && PatternDecl)
+ return PatternDecl->isInlined();
+
+ return false;
+}
+
+/// \brief For an inline function definition in C or C++, determine whether the
/// definition will be externally visible.
///
/// Inline function definitions are always available for inlining optimizations.
@@ -663,9 +688,10 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
assert(isThisDeclarationADefinition() && "Must have the function definition");
- assert(isInline() && "Function must be inline");
+ assert(isInlined() && "Function must be inline");
+ ASTContext &Context = getASTContext();
- if (!getASTContext().getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
+ if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
// GNU inline semantics. Based on a number of examples, we came up with the
// following heuristic: if the "inline" keyword is present on a
// declaration of the function but "extern" is not present on that
@@ -675,7 +701,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
- if (Redecl->isInline() && Redecl->getStorageClass() != Extern)
+ if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern)
return true;
}
@@ -694,7 +720,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
continue;
- if (!Redecl->isInline() || Redecl->getStorageClass() == Extern)
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern)
return true; // Not an inline definition
}
@@ -755,6 +781,59 @@ FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
TemplateOrSpecialization = Info;
}
+bool FunctionDecl::isImplicitlyInstantiable() const {
+ // If this function already has a definition or is invalid, it can't be
+ // implicitly instantiated.
+ if (isInvalidDecl() || getBody())
+ return false;
+
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDefinition:
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ return true;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ // Handled below.
+ break;
+ }
+
+ // Find the actual template from which we will instantiate.
+ const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
+ Stmt *Pattern = 0;
+ if (PatternDecl)
+ Pattern = PatternDecl->getBody(PatternDecl);
+
+ // C++0x [temp.explicit]p9:
+ // Except for inline functions, other explicit instantiation declarations
+ // have the effect of suppressing the implicit instantiation of the entity
+ // to which they refer.
+ if (!Pattern || !PatternDecl)
+ return true;
+
+ return PatternDecl->isInlined();
+}
+
+FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
+ if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
+ while (Primary->getInstantiatedFromMemberTemplate()) {
+ // If we have hit a point where the user provided a specialization of
+ // this template, we're done looking.
+ if (Primary->isMemberSpecialization())
+ break;
+
+ Primary = Primary->getInstantiatedFromMemberTemplate();
+ }
+
+ return Primary->getTemplatedDecl();
+ }
+
+ return getInstantiatedFromMemberFunction();
+}
+
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 224bf877ad24..6cfdcdd3e50e 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -199,7 +199,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Var:
case ImplicitParam:
case ParmVar:
- case OriginalParmVar:
case NonTypeTemplateParm:
case Using:
case UnresolvedUsing:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 457f4c85a047..b4c0c59733e5 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -189,7 +189,10 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context,
// A user-declared copy assignment operator is a non-static non-template
// member function of class X with exactly one parameter of type X, X&,
// const X&, volatile X& or const volatile X&.
- const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
+ const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
+ if (!Method)
+ continue;
+
if (Method->isStatic())
continue;
if (Method->getPrimaryTemplate())
@@ -364,34 +367,36 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
}
}
}
-
+
if (getNumBases() == 0 && getNumVBases() == 0)
return;
-
+
llvm::SmallPtrSet<CanQualType, 8> ConversionFunctions;
if (!inTopClass)
collectConversionFunctions(ConversionFunctions);
-
+
for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
E = vbases_end(); VBase != E; ++VBase) {
- CXXRecordDecl *VBaseClassDecl
- = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
- TopConversionsTypeSet,
- (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
-
+ if (const RecordType *RT = VBase->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *VBaseClassDecl
+ = cast<CXXRecordDecl>(RT->getDecl());
+ VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
+ TopConversionsTypeSet,
+ (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
+ }
}
for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
E = bases_end(); Base != E; ++Base) {
if (Base->isVirtual())
continue;
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- BaseClassDecl->getNestedVisibleConversionFunctions(RD,
- TopConversionsTypeSet,
- (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
-
+ if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(RT->getDecl());
+
+ BaseClassDecl->getNestedVisibleConversionFunctions(RD,
+ TopConversionsTypeSet,
+ (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
+ }
}
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 7f38ac1d9ad0..7b48b724c0eb 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -118,6 +118,27 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
return 0;
}
+/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
+/// with name 'PropertyId' in the primary class; including those in protocols
+/// (direct or indirect) used by the promary class.
+/// FIXME: Convert to DeclContext lookup...
+///
+ObjCPropertyDecl *
+ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
+ IdentifierInfo *PropertyId) const {
+ assert(isa<ObjCInterfaceDecl>(this) && "FindPropertyVisibleInPrimaryClass");
+ for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
+ if ((*I)->getIdentifier() == PropertyId)
+ return *I;
+ const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this);
+ // Look through protocols.
+ for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
+ E = OID->protocol_end(); I != E; ++I)
+ if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+ return P;
+ return 0;
+}
+
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
@@ -288,7 +309,7 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
} else if (ObjCCategoryImplDecl *CImplD =
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
- if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
+ if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
}
@@ -306,7 +327,7 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
} else if (ObjCCategoryImplDecl *CImplD =
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
- if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
+ if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
isInstanceMethod()))
return MD;
@@ -635,7 +656,7 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface);
}
-ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryClass() const {
+ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
return getClassInterface()->FindCategoryDeclaration(getIdentifier());
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 9d0d836cf62b..d9d195016bf3 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -52,7 +52,6 @@ namespace {
void VisitFieldDecl(FieldDecl *D);
void VisitVarDecl(VarDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
- void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
@@ -324,7 +323,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
}
- if (D->isInline()) Out << "inline ";
+ if (D->isInlineSpecified()) Out << "inline ";
if (D->isVirtualAsWritten()) Out << "virtual ";
}
@@ -489,7 +488,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
std::string Name = D->getNameAsString();
QualType T = D->getType();
- if (OriginalParmVarDecl *Parm = dyn_cast<OriginalParmVarDecl>(D))
+ if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
T = Parm->getOriginalType();
T.getAsStringInternal(Name, Policy);
Out << Name;
@@ -508,10 +507,6 @@ void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
VisitVarDecl(D);
}
-void DeclPrinter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
- VisitVarDecl(D);
-}
-
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
Out << "__asm (";
D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation);
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9a1c65416f71..9ebc91afe142 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -1,4 +1,4 @@
-//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
+//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,6 +15,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
@@ -67,6 +68,21 @@ unsigned TemplateParameterList::getMinRequiredArguments() const {
return NumRequiredArgs;
}
+unsigned TemplateParameterList::getDepth() const {
+ if (size() == 0)
+ return 0;
+
+ const NamedDecl *FirstParm = getParam(0);
+ if (const TemplateTypeParmDecl *TTP
+ = dyn_cast<TemplateTypeParmDecl>(FirstParm))
+ return TTP->getDepth();
+ else if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
+ return NTTP->getDepth();
+ else
+ return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
+}
+
//===----------------------------------------------------------------------===//
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -194,8 +210,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
Param != ParamEnd; ++Param) {
if (isa<TemplateTypeParmDecl>(*Param)) {
QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
- TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
- ParamType));
+ TemplateArgs.push_back(TemplateArgument(ParamType));
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
@@ -205,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
TemplateArgs.push_back(TemplateArgument(E));
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
- TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
+ TemplateArgs.push_back(TemplateArgument(TTP));
}
}
@@ -229,6 +244,18 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
+SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
+ return DefaultArgument->getTypeLoc().getFullSourceRange().getBegin();
+}
+
+unsigned TemplateTypeParmDecl::getDepth() const {
+ return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
+}
+
+unsigned TemplateTypeParmDecl::getIndex() const {
+ return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
+}
+
//===----------------------------------------------------------------------===//
// NonTypeTemplateParmDecl Method Implementations
//===----------------------------------------------------------------------===//
@@ -264,34 +291,6 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
}
//===----------------------------------------------------------------------===//
-// TemplateArgument Implementation
-//===----------------------------------------------------------------------===//
-
-TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
- TypeOrValue = reinterpret_cast<uintptr_t>(E);
- StartLoc = E->getSourceRange().getBegin();
-}
-
-/// \brief Construct a template argument pack.
-void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
- bool CopyArgs) {
- assert(isNull() && "Must call setArgumentPack on a null argument");
-
- Kind = Pack;
- Args.NumArgs = NumArgs;
- Args.CopyArgs = CopyArgs;
- if (!Args.CopyArgs) {
- Args.Args = args;
- return;
- }
-
- // FIXME: Allocate in ASTContext
- Args.Args = new TemplateArgument[NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = args[I];
-}
-
-//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
@@ -459,12 +458,19 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
+ TemplateArgumentLoc *ArgInfos, unsigned N,
ClassTemplatePartialSpecializationDecl *PrevDecl) {
+ TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
+ for (unsigned I = 0; I != N; ++I)
+ ClonedArgs[I] = ArgInfos[I];
+
ClassTemplatePartialSpecializationDecl *Result
= new (Context)ClassTemplatePartialSpecializationDecl(Context,
DC, L, Params,
SpecializedTemplate,
- Builder, PrevDecl);
+ Builder,
+ ClonedArgs, N,
+ PrevDecl);
Result->setSpecializationKind(TSK_ExplicitSpecialization);
Context.getTypeDeclType(Result, PrevDecl);
return Result;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index a4de3e5b0f7a..a8ea752a4a7e 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -30,6 +31,91 @@ using namespace clang;
// Primary Expressions.
//===----------------------------------------------------------------------===//
+DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D, SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD)
+ : Expr(DeclRefExprClass, T, TD, VD),
+ DecoratedD(D,
+ (Qualifier? HasQualifierFlag : 0) |
+ (HasExplicitTemplateArgumentList?
+ HasExplicitTemplateArgumentListFlag : 0)),
+ Loc(NameLoc) {
+ if (Qualifier) {
+ NameQualifier *NQ = getNameQualifier();
+ NQ->NNS = Qualifier;
+ NQ->Range = QualifierRange;
+ }
+
+ if (HasExplicitTemplateArgumentList) {
+ ExplicitTemplateArgumentList *ETemplateArgs
+ = getExplicitTemplateArgumentList();
+ ETemplateArgs->LAngleLoc = LAngleLoc;
+ ETemplateArgs->RAngleLoc = RAngleLoc;
+ ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs;
+
+ TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
+ for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I)
+ new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]);
+ }
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ QualType T, bool TD, bool VD) {
+ return Create(Context, Qualifier, QualifierRange, D, NameLoc,
+ false, SourceLocation(), 0, 0, SourceLocation(),
+ T, TD, VD);
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD) {
+ std::size_t Size = sizeof(DeclRefExpr);
+ if (Qualifier != 0)
+ Size += sizeof(NameQualifier);
+
+ if (HasExplicitTemplateArgumentList)
+ Size += sizeof(ExplicitTemplateArgumentList) +
+ sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs;
+
+ void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
+ return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
+ HasExplicitTemplateArgumentList,
+ LAngleLoc,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ RAngleLoc,
+ T, TD, VD);
+}
+
+SourceRange DeclRefExpr::getSourceRange() const {
+ // FIXME: Does not handle multi-token names well, e.g., operator[].
+ SourceRange R(Loc);
+
+ if (hasQualifier())
+ R.setBegin(getQualifierRange().getBegin());
+ if (hasExplicitTemplateArgumentList())
+ R.setEnd(getRAngleLoc());
+ return R;
+}
+
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
@@ -343,7 +429,7 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, NamedDecl *memberdecl,
SourceLocation l, bool has_explicit,
SourceLocation langle,
- const TemplateArgument *targs, unsigned numtargs,
+ const TemplateArgumentLoc *targs, unsigned numtargs,
SourceLocation rangle, QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent() || (qual && qual->isDependent()),
@@ -365,9 +451,9 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
ETemplateArgs->RAngleLoc = rangle;
ETemplateArgs->NumTemplateArgs = numtargs;
- TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
+ TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
for (unsigned I = 0; I < numtargs; ++I)
- new (TemplateArgs + I) TemplateArgument(targs[I]);
+ new (TemplateArgs + I) TemplateArgumentLoc(targs[I]);
}
}
@@ -378,7 +464,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
SourceLocation l,
bool has_explicit,
SourceLocation langle,
- const TemplateArgument *targs,
+ const TemplateArgumentLoc *targs,
unsigned numtargs,
SourceLocation rangle,
QualType ty) {
@@ -388,7 +474,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
if (has_explicit)
Size += sizeof(ExplicitTemplateArgumentList) +
- sizeof(TemplateArgument) * numtargs;
+ sizeof(TemplateArgumentLoc) * numtargs;
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
@@ -418,6 +504,8 @@ const char *CastExpr::getCastKindName() const {
return "NullToMemberPointer";
case CastExpr::CK_BaseToDerivedMemberPointer:
return "BaseToDerivedMemberPointer";
+ case CastExpr::CK_DerivedToBaseMemberPointer:
+ return "DerivedToBaseMemberPointer";
case CastExpr::CK_UserDefinedConversion:
return "UserDefinedConversion";
case CastExpr::CK_ConstructorConversion:
@@ -610,7 +698,7 @@ Stmt *BlockExpr::getBody() {
/// with location to warn on and the source range[s] to report with the
/// warning.
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2) const {
+ SourceRange &R2, ASTContext &Ctx) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
@@ -623,7 +711,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
- isUnusedResultAWarning(Loc, R1, R2);
+ isUnusedResultAWarning(Loc, R1, R2, Ctx);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@@ -636,17 +724,18 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false; // Not a warning.
case UnaryOperator::Deref:
// Dereferencing a volatile pointer is a side-effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
break;
case UnaryOperator::Real:
case UnaryOperator::Imag:
// accessing a piece of a volatile complex is a side-effect.
- if (UO->getSubExpr()->getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
+ .isVolatileQualified())
return false;
break;
case UnaryOperator::Extension:
- return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
@@ -656,8 +745,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const BinaryOperator *BO = cast<BinaryOperator>(this);
// Consider comma to have side effects if the LHS or RHS does.
if (BO->getOpcode() == BinaryOperator::Comma)
- return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
- BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return (BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
+ BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
if (BO->isAssignmentOp())
return false;
@@ -674,15 +763,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
if (Exp->getLHS() &&
- Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
+ Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
return true;
- return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
case MemberExprClass:
// If the base pointer or element is to a volatile pointer/field, accessing
// it is a side effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
Loc = cast<MemberExpr>(this)->getMemberLoc();
R1 = SourceRange(Loc, Loc);
@@ -692,7 +781,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ArraySubscriptExprClass:
// If the base pointer or element is to a volatile pointer/field, accessing
// it is a side effect.
- if (getType().isVolatileQualified())
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
@@ -750,7 +839,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
- return E->isUnusedResultAWarning(Loc, R1, R2);
+ return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
@@ -768,20 +857,20 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
- return cast<CastExpr>(this)->getSubExpr()
- ->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CastExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
- return cast<ImplicitCastExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<ImplicitCastExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXDefaultArgExprClass:
- return cast<CXXDefaultArgExpr>(this)
- ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXDefaultArgExpr>(this)
+ ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@@ -789,11 +878,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case CXXDeleteExprClass:
return false;
case CXXBindTemporaryExprClass:
- return cast<CXXBindTemporaryExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXBindTemporaryExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXExprWithTemporariesClass:
- return cast<CXXExprWithTemporaries>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast<CXXExprWithTemporaries>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
}
}
@@ -855,8 +944,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType())
return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx);
return LV_Valid;
- case DeclRefExprClass:
- case QualifiedDeclRefExprClass: { // C99 6.5.1p2
+ case DeclRefExprClass: { // C99 6.5.1p2
const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
if (DeclCanBeLvalue(RefdDecl, Ctx))
return LV_Valid;
@@ -1042,6 +1130,18 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
}
+ case TemplateIdRefExprClass: {
+ const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this);
+ TemplateName Template = TID->getTemplateName();
+ NamedDecl *ND = Template.getAsTemplateDecl();
+ if (!ND)
+ ND = Template.getAsOverloadedFunctionDecl();
+ if (ND && DeclCanBeLvalue(ND, Ctx))
+ return LV_Valid;
+
+ break;
+ }
+
default:
break;
}
@@ -1133,8 +1233,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
- case DeclRefExprClass:
- case QualifiedDeclRefExprClass: {
+ case DeclRefExprClass: {
const Decl *D = cast<DeclRefExpr>(this)->getDecl();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage())
@@ -1432,7 +1531,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return ICEDiag(2, E->getLocStart());
}
case Expr::DeclRefExprClass:
- case Expr::QualifiedDeclRefExprClass:
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
return NoDiag();
if (Ctx.getLangOptions().CPlusPlus &&
@@ -1442,16 +1540,35 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// type initialized by an ICE can be used in ICEs.
if (const VarDecl *Dcl =
dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) {
- if (Dcl->isInitKnownICE()) {
- // We have already checked whether this subexpression is an
- // integral constant expression.
- if (Dcl->isInitICE())
- return NoDiag();
- else
- return ICEDiag(2, E->getLocStart());
- }
+ Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers();
+ if (Quals.hasVolatile() || !Quals.hasConst())
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+
+ // Look for the definition of this variable, which will actually have
+ // an initializer.
+ const VarDecl *Def = 0;
+ const Expr *Init = Dcl->getDefinition(Def);
+ if (Init) {
+ if (Def->isInitKnownICE()) {
+ // We have already checked whether this subexpression is an
+ // integral constant expression.
+ if (Def->isInitICE())
+ return NoDiag();
+ else
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+ }
- if (const Expr *Init = Dcl->getInit()) {
+ // C++ [class.static.data]p4:
+ // If a static data member is of const integral or const
+ // enumeration type, its declaration in the class definition can
+ // specify a constant-initializer which shall be an integral
+ // constant expression (5.19). In that case, the member can appear
+ // in integral constant expressions.
+ if (Def->isOutOfLine()) {
+ Dcl->setInitKnownICE(Ctx, false);
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+ }
+
ICEDiag Result = CheckICE(Init, Ctx);
// Cache the result of the ICE test.
Dcl->setInitKnownICE(Ctx, Result.Val == 0);
@@ -1654,7 +1771,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
}
EvalResult EvalResult;
if (!Evaluate(EvalResult, Ctx))
- assert(0 && "ICE cannot be evaluated!");
+ llvm::llvm_unreachable("ICE cannot be evaluated!");
assert(!EvalResult.HasSideEffects && "ICE with side effects!");
assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
Result = EvalResult.Val.getInt();
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index cba0e220952e..7c6fc41ef12b 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -151,7 +151,7 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc)
: Expr(TemplateIdRefExprClass, T,
@@ -164,10 +164,10 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc),
RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) {
- TemplateArgument *StoredTemplateArgs
- = reinterpret_cast<TemplateArgument *> (this+1);
+ TemplateArgumentLoc *StoredTemplateArgs
+ = reinterpret_cast<TemplateArgumentLoc *> (this+1);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
- new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
+ new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
}
TemplateIdRefExpr *
@@ -176,19 +176,19 @@ TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
- sizeof(TemplateArgument) * NumTemplateArgs);
+ sizeof(TemplateArgumentLoc) * NumTemplateArgs);
return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
TemplateNameLoc, LAngleLoc, TemplateArgs,
NumTemplateArgs, RAngleLoc);
}
void TemplateIdRefExpr::DoDestroy(ASTContext &Context) {
- const TemplateArgument *TemplateArgs = getTemplateArgs();
+ const TemplateArgumentLoc *TemplateArgs = getTemplateArgs();
for (unsigned I = 0; I != NumTemplateArgs; ++I)
- if (Expr *E = TemplateArgs[I].getAsExpr())
+ if (Expr *E = TemplateArgs[I].getArgument().getAsExpr())
E->Destroy(Context);
this->~TemplateIdRefExpr();
Context.Deallocate(this);
@@ -528,7 +528,7 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc)
: Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
@@ -545,9 +545,9 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
ETemplateArgs->RAngleLoc = RAngleLoc;
ETemplateArgs->NumTemplateArgs = NumTemplateArgs;
- TemplateArgument *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
+ TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
for (unsigned I = 0; I < NumTemplateArgs; ++I)
- new (SavedTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
+ new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
}
}
@@ -562,7 +562,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
if (!HasExplicitTemplateArgs)
@@ -573,7 +573,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C,
void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) +
sizeof(ExplicitTemplateArgumentList) +
- sizeof(TemplateArgument) * NumTemplateArgs,
+ sizeof(TemplateArgumentLoc) * NumTemplateArgs,
llvm::alignof<CXXUnresolvedMemberExpr>());
return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
Qualifier, QualifierRange,
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 94d22998ebbe..7862c57c2d47 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -58,7 +58,8 @@ struct EvalInfo {
static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
-static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info);
+static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
+ EvalInfo &Info);
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
@@ -151,6 +152,67 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
return Result;
}
+namespace {
+class VISIBILITY_HIDDEN HasSideEffect
+ : public StmtVisitor<HasSideEffect, bool> {
+ EvalInfo &Info;
+public:
+
+ HasSideEffect(EvalInfo &info) : Info(info) {}
+
+ // Unhandled nodes conservatively default to having side effects.
+ bool VisitStmt(Stmt *S) {
+ return true;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return false;
+ }
+ // We don't want to evaluate BlockExprs multiple times, as they generate
+ // a ton of code.
+ bool VisitBlockExpr(BlockExpr *E) { return true; }
+ bool VisitPredefinedExpr(PredefinedExpr *E) { return false; }
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
+ { return Visit(E->getInitializer()); }
+ bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); }
+ bool VisitIntegerLiteral(IntegerLiteral *E) { return false; }
+ bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
+ bool VisitStringLiteral(StringLiteral *E) { return false; }
+ bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
+ bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
+ { return Visit(E->getLHS()) || Visit(E->getRHS()); }
+ bool VisitChooseExpr(ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitBinAssign(BinaryOperator *E) { return true; }
+ bool VisitCompoundAssignOperator(BinaryOperator *E) { return true; }
+ bool VisitBinaryOperator(BinaryOperator *E)
+ { return Visit(E->getLHS()) || Visit(E->getRHS()); }
+ bool VisitUnaryPreInc(UnaryOperator *E) { return true; }
+ bool VisitUnaryPostInc(UnaryOperator *E) { return true; }
+ bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
+ bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
+ bool VisitUnaryDeref(UnaryOperator *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return Visit(E->getSubExpr());
+ }
+ bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+};
+
+bool HasSideEffects(const Expr* E, ASTContext &Ctx) {
+ Expr::EvalResult Result;
+ EvalInfo Info(Ctx, Result);
+
+ return HasSideEffect(Info).Visit(const_cast<Expr*>(E));
+}
+
+} // end anonymous namespace
+
//===----------------------------------------------------------------------===//
// LValue Evaluation
//===----------------------------------------------------------------------===//
@@ -208,8 +270,9 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (!VD->getType()->isReferenceType())
return APValue(E, 0);
// FIXME: Check whether VD might be overridden!
- if (VD->getInit())
- return Visit(VD->getInit());
+ const VarDecl *Def = 0;
+ if (const Expr *Init = VD->getDefinition(Def))
+ return Visit(const_cast<Expr *>(Init));
}
return APValue();
@@ -793,11 +856,14 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
// In C++, const, non-volatile integers initialized with ICEs are ICEs.
// In C, they can also be folded, although they are not ICEs.
- if (E->getType().getCVRQualifiers() == Qualifiers::Const) {
+ if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers()
+ == Qualifiers::Const) {
if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
- if (APValue *V = D->getEvaluatedValue())
- return Success(V->getInt(), E);
- if (const Expr *Init = D->getInit()) {
+ const VarDecl *Def = 0;
+ if (const Expr *Init = D->getDefinition(Def)) {
+ if (APValue *V = D->getEvaluatedValue())
+ return Success(V->getInt(), E);
+
if (Visit(const_cast<Expr*>(Init))) {
// Cache the evaluated value in the variable declaration.
D->setEvaluatedValue(Info.Ctx, Result);
@@ -873,6 +939,40 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
switch (E->isBuiltinCall(Info.Ctx)) {
default:
return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+ case Builtin::BI__builtin_object_size: {
+ const Expr *Arg = E->getArg(0)->IgnoreParens();
+ Expr::EvalResult Base;
+ if (Arg->EvaluateAsAny(Base, Info.Ctx)
+ && Base.Val.getKind() == APValue::LValue
+ && !Base.HasSideEffects)
+ if (const Expr *LVBase = Base.Val.getLValueBase())
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVBase)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!VD->getType()->isIncompleteType()
+ && VD->getType()->isObjectType()
+ && !VD->getType()->isVariablyModifiedType()
+ && !VD->getType()->isDependentType()) {
+ uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8;
+ uint64_t Offset = Base.Val.getLValueOffset();
+ if (Offset <= Size)
+ Size -= Base.Val.getLValueOffset();
+ else
+ Size = 0;
+ return Success(Size, E);
+ }
+ }
+ }
+
+ if (HasSideEffects(E->getArg(0), Info.Ctx)) {
+ if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
+ return Success(-1ULL, E);
+ return Success(0, E);
+ }
+
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+ }
+
case Builtin::BI__builtin_classify_type:
return Success(EvaluateBuiltinClassifyType(E), E);
@@ -1801,6 +1901,33 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
return true;
}
+bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
+ EvalInfo Info(Ctx, Result, true);
+
+ if (getType()->isVectorType()) {
+ if (!EvaluateVector(this, Result.Val, Info))
+ return false;
+ } else if (getType()->isIntegerType()) {
+ if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this)))
+ return false;
+ } else if (getType()->hasPointerRepresentation()) {
+ if (!EvaluatePointer(this, Result.Val, Info))
+ return false;
+ } else if (getType()->isRealFloatingType()) {
+ llvm::APFloat f(0.0);
+ if (!EvaluateFloat(this, f, Info))
+ return false;
+
+ Result.Val = APValue(f);
+ } else if (getType()->isAnyComplexType()) {
+ if (!EvaluateComplex(this, Result.Val, Info))
+ return false;
+ } else
+ return false;
+
+ return true;
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index c79cc3c1dbb1..0b159c3a7bd8 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -47,6 +47,8 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (!i->isVirtual()) {
+ assert(!i->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
// Skip the PrimaryBase here, as it is laid down first.
@@ -82,6 +84,8 @@ void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
// Now traverse all bases and find primary bases for them.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
+ assert(!i->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
@@ -97,6 +101,8 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
const CXXRecordDecl *&FirstPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
+ assert(!i->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (!i->isVirtual()) {
@@ -123,6 +129,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// indirect bases, and record all their primary virtual base classes.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
+ assert(!i->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
IdentifyPrimaryBases(Base);
@@ -173,6 +181,8 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
+ assert(!i->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
#if 0
@@ -235,6 +245,8 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
// Check bases.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
if (I->isVirtual())
continue;
@@ -305,6 +317,8 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
// Update bases.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
if (I->isVirtual())
continue;
diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h
index 6e4cdd2fe2ee..b57b37d0df4d 100644
--- a/lib/AST/RecordLayoutBuilder.h
+++ b/lib/AST/RecordLayoutBuilder.h
@@ -12,7 +12,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <map>
namespace clang {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 2af19765dfaa..4bd7f964be6c 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -473,14 +473,14 @@ void StmtPrinter::VisitExpr(Expr *Node) {
}
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
OS << Node->getDecl()->getNameAsString();
-}
-
-void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) {
- NamedDecl *D = Node->getDecl();
-
- Node->getQualifier()->print(OS, Policy);
- OS << D->getNameAsString();
+ if (Node->hasExplicitTemplateArgumentList())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
}
void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index c4d42f6be228..02e0c74bb63a 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -60,7 +60,10 @@ namespace {
/// \brief Visit template arguments that occur within an expression or
/// statement.
- void VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs);
+ void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs);
+
+ /// \brief Visit a single template argument.
+ void VisitTemplateArgument(const TemplateArgument &Arg);
};
}
@@ -206,7 +209,9 @@ void StmtProfiler::VisitExpr(Expr *S) {
void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
VisitExpr(S);
+ VisitNestedNameSpecifier(S->getQualifier());
VisitDecl(S->getDecl());
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) {
@@ -521,11 +526,6 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
VisitType(S->getQueriedType());
}
-void StmtProfiler::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *S) {
- VisitDeclRefExpr(S);
- VisitNestedNameSpecifier(S->getQualifier());
-}
-
void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) {
VisitExpr(S);
VisitName(S->getDeclName());
@@ -677,39 +677,42 @@ void StmtProfiler::VisitTemplateName(TemplateName Name) {
Name.Profile(ID);
}
-void StmtProfiler::VisitTemplateArguments(const TemplateArgument *Args,
+void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs) {
ID.AddInteger(NumArgs);
- for (unsigned I = 0; I != NumArgs; ++I) {
- const TemplateArgument &Arg = Args[I];
-
- // Mostly repetitive with TemplateArgument::Profile!
- ID.AddInteger(Arg.getKind());
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- break;
-
- case TemplateArgument::Type:
- VisitType(Arg.getAsType());
- break;
-
- case TemplateArgument::Declaration:
- VisitDecl(Arg.getAsDecl());
- break;
-
- case TemplateArgument::Integral:
- Arg.getAsIntegral()->Profile(ID);
- VisitType(Arg.getIntegralType());
- break;
-
- case TemplateArgument::Expression:
- Visit(Arg.getAsExpr());
- break;
-
- case TemplateArgument::Pack:
- VisitTemplateArguments(Arg.pack_begin(), Arg.pack_size());
- break;
- }
+ for (unsigned I = 0; I != NumArgs; ++I)
+ VisitTemplateArgument(Args[I].getArgument());
+}
+
+void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
+ // Mostly repetitive with TemplateArgument::Profile!
+ ID.AddInteger(Arg.getKind());
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Declaration:
+ VisitDecl(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::Integral:
+ Arg.getAsIntegral()->Profile(ID);
+ VisitType(Arg.getIntegralType());
+ break;
+
+ case TemplateArgument::Expression:
+ Visit(Arg.getAsExpr());
+ break;
+
+ case TemplateArgument::Pack:
+ const TemplateArgument *Pack = Arg.pack_begin();
+ for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i)
+ VisitTemplateArgument(Pack[i]);
+ break;
}
}
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
new file mode 100644
index 000000000000..94e1ca1e06e7
--- /dev/null
+++ b/lib/AST/TemplateBase.cpp
@@ -0,0 +1,97 @@
+//===--- TemplateBase.cpp - Common template AST class 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 common classes used throughout C++ template
+// representations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FoldingSet.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TypeLoc.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TemplateArgument Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Construct a template argument pack.
+void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
+ bool CopyArgs) {
+ assert(isNull() && "Must call setArgumentPack on a null argument");
+
+ Kind = Pack;
+ Args.NumArgs = NumArgs;
+ Args.CopyArgs = CopyArgs;
+ if (!Args.CopyArgs) {
+ Args.Args = args;
+ return;
+ }
+
+ // FIXME: Allocate in ASTContext
+ Args.Args = new TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I] = args[I];
+}
+
+void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
+ ASTContext &Context) const {
+ ID.AddInteger(Kind);
+ switch (Kind) {
+ case Null:
+ break;
+
+ case Type:
+ getAsType().Profile(ID);
+ break;
+
+ case Declaration:
+ ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
+ break;
+
+ case Integral:
+ getAsIntegral()->Profile(ID);
+ getIntegralType().Profile(ID);
+ break;
+
+ case Expression:
+ getAsExpr()->Profile(ID, Context, true);
+ break;
+
+ case Pack:
+ ID.AddInteger(Args.NumArgs);
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I].Profile(ID, Context);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateArgumentLoc Implementation
+//===----------------------------------------------------------------------===//
+
+SourceRange TemplateArgumentLoc::getSourceRange() const {
+ switch (Argument.getKind()) {
+ case TemplateArgument::Expression:
+ return getSourceExpression()->getSourceRange();
+ case TemplateArgument::Declaration:
+ return getSourceDeclExpression()->getSourceRange();
+ case TemplateArgument::Type:
+ return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange();
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return SourceRange();
+ }
+
+ // Silence bonus gcc warning.
+ return SourceRange();
+}
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index 24588bc5f11f..5b4cf0ad94f6 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -56,7 +56,7 @@ void
TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS) const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
- OS << Template->getIdentifier()->getName();
+ OS << Template->getNameAsString();
else if (OverloadedFunctionDecl *Ovl
= Storage.dyn_cast<OverloadedFunctionDecl *>())
OS << Ovl->getNameAsString();
@@ -70,8 +70,11 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
if (!SuppressNNS && DTN->getQualifier())
DTN->getQualifier()->print(OS, Policy);
OS << "template ";
- // FIXME: Shouldn't we have a more general kind of name?
- OS << DTN->getName()->getName();
+
+ if (DTN->isIdentifier())
+ OS << DTN->getIdentifier()->getName();
+ else
+ OS << "operator " << getOperatorSpelling(DTN->getOperator());
}
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5fb0178834ff..3608d34c691d 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -224,6 +224,8 @@ QualType Type::getPointeeType() const {
return OPT->getPointeeType();
if (const BlockPointerType *BPT = getAs<BlockPointerType>())
return BPT->getPointeeType();
+ if (const ReferenceType *RT = getAs<ReferenceType>())
+ return RT->getPointeeType();
return QualType();
}
@@ -791,40 +793,48 @@ bool EnumType::classof(const TagType *TT) {
return isa<EnumDecl>(TT->getDecl());
}
-bool
-TemplateSpecializationType::
-anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
- for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
- switch (Args[Idx].getKind()) {
- case TemplateArgument::Null:
- assert(false && "Should not have a NULL template argument");
- break;
-
- case TemplateArgument::Type:
- if (Args[Idx].getAsType()->isDependentType())
- return true;
- break;
-
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- // Never dependent
- break;
-
- case TemplateArgument::Expression:
- if (Args[Idx].getAsExpr()->isTypeDependent() ||
- Args[Idx].getAsExpr()->isValueDependent())
- return true;
- break;
-
- case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
- }
+static bool isDependent(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Should not have a NULL template argument");
+ return false;
+
+ case TemplateArgument::Type:
+ return Arg.getAsType()->isDependentType();
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ // Never dependent
+ return false;
+
+ case TemplateArgument::Expression:
+ return (Arg.getAsExpr()->isTypeDependent() ||
+ Arg.getAsExpr()->isValueDependent());
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ return false;
}
return false;
}
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
+ for (unsigned i = 0; i != N; ++i)
+ if (isDependent(Args[i].getArgument()))
+ return true;
+ return false;
+}
+
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
+ for (unsigned i = 0; i != N; ++i)
+ if (isDependent(Args[i]))
+ return true;
+ return false;
+}
+
TemplateSpecializationType::
TemplateSpecializationType(ASTContext &Context, TemplateName T,
const TemplateArgument *Args,
@@ -1260,6 +1270,38 @@ void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, co
getReplacementType().getAsStringInternal(InnerString, Policy);
}
+static void PrintTemplateArgument(std::string &Buffer,
+ const TemplateArgument &Arg,
+ const PrintingPolicy &Policy) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Null template argument");
+ break;
+
+ case TemplateArgument::Type:
+ Arg.getAsType().getAsStringInternal(Buffer, Policy);
+ break;
+
+ case TemplateArgument::Declaration:
+ Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
+ break;
+
+ case TemplateArgument::Integral:
+ Buffer = Arg.getAsIntegral()->toString(10, true);
+ break;
+
+ case TemplateArgument::Expression: {
+ llvm::raw_string_ostream s(Buffer);
+ Arg.getAsExpr()->printPretty(s, 0, Policy);
+ break;
+ }
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
+ }
+}
+
std::string
TemplateSpecializationType::PrintTemplateArgumentList(
const TemplateArgument *Args,
@@ -1273,32 +1315,41 @@ TemplateSpecializationType::PrintTemplateArgumentList(
// Print the argument into a string.
std::string ArgString;
- switch (Args[Arg].getKind()) {
- case TemplateArgument::Null:
- assert(false && "Null template argument");
- break;
-
- case TemplateArgument::Type:
- Args[Arg].getAsType().getAsStringInternal(ArgString, Policy);
- break;
-
- case TemplateArgument::Declaration:
- ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString();
- break;
-
- case TemplateArgument::Integral:
- ArgString = Args[Arg].getAsIntegral()->toString(10, true);
- break;
-
- case TemplateArgument::Expression: {
- llvm::raw_string_ostream s(ArgString);
- Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
- break;
- }
- case TemplateArgument::Pack:
- assert(0 && "FIXME: Implement!");
- break;
- }
+ PrintTemplateArgument(ArgString, Args[Arg], Policy);
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ SpecString += '>';
+
+ return SpecString;
+}
+
+// Sadly, repeat all that with TemplateArgLoc.
+std::string TemplateSpecializationType::
+PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ const PrintingPolicy &Policy) {
+ std::string SpecString;
+ SpecString += '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
// If this is the first argument and its string representation
// begins with the global scope specifier ('::foo'), add a space
diff --git a/lib/Analysis/AttrNonNullChecker.cpp b/lib/Analysis/AttrNonNullChecker.cpp
new file mode 100644
index 000000000000..1cf5d0c4af2d
--- /dev/null
+++ b/lib/Analysis/AttrNonNullChecker.cpp
@@ -0,0 +1,100 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *AttrNonNullChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const GRState *originalState = state;
+
+ // Check if the callee has a 'nonnull' attribute.
+ SVal X = state->getSVal(CE->getCallee());
+
+ const FunctionDecl* FD = X.getAsFunctionDecl();
+ if (!FD)
+ return;
+
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+ if (!Att)
+ return;
+
+ // Iterate through the arguments of CE and check them for null.
+ unsigned idx = 0;
+
+ for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+ ++I, ++idx) {
+
+ if (!Att->isNonNull(idx))
+ continue;
+
+ const SVal &V = state->getSVal(*I);
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
+
+ if (!DV)
+ continue;
+
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
+
+ if (stateNull && !stateNotNull) {
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
+
+ // Lazily allocate the BugType object if it hasn't already been
+ // created. Ownership is transferred to the BugReporter object once
+ // the BugReport is passed to 'EmitWarning'.
+ if (!BT)
+ BT = new BugType("Argument with 'nonnull' attribute passed null",
+ "API");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT,
+ "Null pointer passed as an argument to a "
+ "'nonnull' parameter", errorNode);
+
+ // Highlight the range of the argument that was null.
+ const Expr *arg = *I;
+ R->addRange(arg->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
+
+ // Emit the bug report.
+ C.EmitReport(R);
+ }
+
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+
+ // If a pointer value passed the check we should assume that it is
+ // indeed not null from this point forward.
+ assert(stateNotNull);
+ state = stateNotNull;
+ }
+
+ // If we reach here all of the arguments passed the nonnull check.
+ // If 'state' has been updated generated a new node.
+ if (state != originalState)
+ C.addTransition(C.GenerateNode(CE, state));
+}
diff --git a/lib/Analysis/BadCallChecker.cpp b/lib/Analysis/BadCallChecker.cpp
new file mode 100644
index 000000000000..33bb5158d2b9
--- /dev/null
+++ b/lib/Analysis/BadCallChecker.cpp
@@ -0,0 +1,44 @@
+//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for bad callee at call sites.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *BadCallChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const Expr *Callee = CE->getCallee()->IgnoreParens();
+ SVal L = C.getState()->getSVal(Callee);
+
+ if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
+ if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+ if (!BT)
+ BT = new BuiltinBug(0, "Invalid function call",
+ "Called function pointer is a null or undefined pointer value");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetCalleeExpr(N));
+
+ C.EmitReport(R);
+ }
+ }
+}
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index aa2d0ab5a763..4781d5ec243e 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -535,4 +535,5 @@ void clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
RegisterNSErrorChecks(BR, Eng, D);
+ RegisterNSAutoreleasePoolChecks(Eng);
}
diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h
index 1271ae4ab1c0..ea4d3ecfcaee 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.h
+++ b/lib/Analysis/BasicObjCFoundationChecks.h
@@ -42,6 +42,7 @@ GRSimpleAPICheck *CreateAuditCFRetainRelease(ASTContext& Ctx,
BugReporter& BR);
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng, const Decl &D);
+void RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng);
} // end clang namespace
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index d81d83c7bfa2..888af9bd57a4 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -92,19 +92,17 @@ public:
void iterBindings(Store store, BindingsHandler& f);
- const GRState *BindDecl(const GRState *state, const VarDecl *VD,
- const LocationContext *LC, SVal InitVal) {
- return state->makeWithStore(BindDeclInternal(state->getStore(),VD, LC,
+ const GRState *BindDecl(const GRState *state, const VarRegion *VR,
+ SVal InitVal) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VR,
&InitVal));
}
- const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *VD,
- const LocationContext *LC) {
- return state->makeWithStore(BindDeclInternal(state->getStore(), VD, LC, 0));
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarRegion *VR) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VR, 0));
}
- Store BindDeclInternal(Store store, const VarDecl *VD,
- const LocationContext *LC, SVal *InitVal);
+ Store BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal);
static inline BindingsTy GetBindings(Store store) {
return BindingsTy(static_cast<const BindingsTy::TreeTy*>(store));
@@ -532,11 +530,11 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
return St;
}
-Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
- const LocationContext *LC,
+Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
SVal* InitVal) {
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+ const VarDecl *VD = VR->getDecl();
// BasicStore does not model arrays and structs.
if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
@@ -564,16 +562,16 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
if (!InitVal) {
QualType T = VD->getType();
if (Loc::IsLocType(T))
- store = BindInternal(store, getLoc(VD, LC),
+ store = BindInternal(store, loc::MemRegionVal(VR),
loc::ConcreteInt(BasicVals.getValue(0, T)));
else if (T->isIntegerType())
- store = BindInternal(store, getLoc(VD, LC),
+ store = BindInternal(store, loc::MemRegionVal(VR),
nonloc::ConcreteInt(BasicVals.getValue(0, T)));
else {
// assert(0 && "ignore other types of variables");
}
} else {
- store = BindInternal(store, getLoc(VD, LC), *InitVal);
+ store = BindInternal(store, loc::MemRegionVal(VR), *InitVal);
}
}
} else {
@@ -581,7 +579,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
QualType T = VD->getType();
if (ValMgr.getSymbolManager().canSymbolicate(T)) {
SVal V = InitVal ? *InitVal : UndefinedVal();
- store = BindInternal(store, getLoc(VD, LC), V);
+ store = BindInternal(store, loc::MemRegionVal(VR), V);
}
}
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index c629ad1d9612..03614e83398f 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -193,20 +193,6 @@ public:
} // end anonymous namespace
//===----------------------------------------------------------------------===//
-// Selector creation functions.
-//===----------------------------------------------------------------------===//
-
-static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
- IdentifierInfo* II = &Ctx.Idents.get(name);
- return Ctx.Selectors.getSelector(0, &II);
-}
-
-static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
- IdentifierInfo* II = &Ctx.Idents.get(name);
- return Ctx.Selectors.getSelector(1, &II);
-}
-
-//===----------------------------------------------------------------------===//
// Type querying functions.
//===----------------------------------------------------------------------===//
@@ -1031,11 +1017,25 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// Eventually this can be improved by recognizing that the pixel
// buffer passed to CVPixelBufferCreateWithBytes is released via
// a callback and doing full IPA to make sure this is done correctly.
+ // FIXME: This function has an out parameter that returns an
+ // allocated object.
ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
DoNothing);
}
break;
+
+ case 29:
+ if (!memcmp(FName, "CGBitmapContextCreateWithData", 29)) {
+ // FIXES: <rdar://problem/7358899>
+ // Eventually this can be improved by recognizing that 'releaseInfo'
+ // passed to CGBitmapContextCreateWithData is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ ScratchArgs = AF.Add(ScratchArgs, 8, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing,DoNothing);
+ }
+ break;
case 32:
if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
@@ -1899,7 +1899,7 @@ public:
virtual ~CFRefCount() {}
- void RegisterChecks(BugReporter &BR);
+ void RegisterChecks(GRExprEngine &Eng);
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
Printers.push_back(new BindingsPrinter());
@@ -2193,7 +2193,9 @@ namespace {
};
} // end anonymous namespace
-void CFRefCount::RegisterChecks(BugReporter& BR) {
+void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
+ BugReporter &BR = Eng.getBugReporter();
+
useAfterRelease = new UseAfterRelease(this);
BR.Register(useAfterRelease);
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 89c1783cc2f5..cd4697f2f324 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -3,6 +3,8 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangAnalysis
AnalysisContext.cpp
AnalysisManager.cpp
+ AttrNonNullChecker.cpp
+ BadCallChecker.cpp
BasicConstraintManager.cpp
BasicObjCFoundationChecks.cpp
BasicStore.cpp
@@ -14,11 +16,12 @@ add_clang_library(clangAnalysis
CallGraph.cpp
CallInliner.cpp
CheckDeadStores.cpp
- CheckNSError.cpp
CheckObjCDealloc.cpp
CheckObjCInstMethSignature.cpp
CheckObjCUnusedIVars.cpp
CheckSecuritySyntaxOnly.cpp
+ DereferenceChecker.cpp
+ DivZeroChecker.cpp
Environment.cpp
ExplodedGraph.cpp
GRBlockCounter.cpp
@@ -28,6 +31,8 @@ add_clang_library(clangAnalysis
GRState.cpp
LiveVariables.cpp
MemRegion.cpp
+ NSAutoreleasePoolChecker.cpp
+ NSErrorChecker.cpp
PathDiagnostic.cpp
RangeConstraintManager.cpp
RegionStore.cpp
@@ -37,8 +42,11 @@ add_clang_library(clangAnalysis
SimpleSValuator.cpp
Store.cpp
SymbolManager.cpp
+ UndefinedArgChecker.cpp
+ UndefinedAssignmentChecker.cpp
UninitializedValues.cpp
ValueManager.cpp
+ VLASizeChecker.cpp
)
add_dependencies(clangAnalysis ClangDiagnosticAnalysis)
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index ae8845db63ae..17dc0685f82f 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -68,10 +68,8 @@ CallGraph::~CallGraph() {
}
}
-void CallGraph::addTU(ASTUnit &AST) {
- ASTContext &Ctx = AST.getASTContext();
+void CallGraph::addTU(ASTContext& Ctx) {
DeclContext *DC = Ctx.getTranslationUnitDecl();
-
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
I != E; ++I) {
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp
index 1a900f897678..2d9b53163f6a 100644
--- a/lib/Analysis/CheckObjCUnusedIVars.cpp
+++ b/lib/Analysis/CheckObjCUnusedIVars.cpp
@@ -62,6 +62,29 @@ static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) {
I->second = Used;
}
+static void Scan(IvarUsageMap& M, const ObjCContainerDecl* D) {
+ // Scan the methods for accesses.
+ for (ObjCContainerDecl::instmeth_iterator I = D->instmeth_begin(),
+ E = D->instmeth_end(); I!=E; ++I)
+ Scan(M, (*I)->getBody());
+
+ if (const ObjCImplementationDecl *ID = dyn_cast<ObjCImplementationDecl>(D)) {
+ // Scan for @synthesized property methods that act as setters/getters
+ // to an ivar.
+ for (ObjCImplementationDecl::propimpl_iterator I = ID->propimpl_begin(),
+ E = ID->propimpl_end(); I!=E; ++I)
+ Scan(M, *I);
+
+ // Scan the associated categories as well.
+ for (const ObjCCategoryDecl *CD =
+ ID->getClassInterface()->getCategoryList(); CD ;
+ CD = CD->getNextClassCategory()) {
+ if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
+ Scan(M, CID);
+ }
+ }
+}
+
void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
BugReporter &BR) {
@@ -88,16 +111,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
if (M.empty())
return;
- // Now scan the methods for accesses.
- for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
- E = D->instmeth_end(); I!=E; ++I)
- Scan(M, (*I)->getBody());
-
- // Scan for @synthesized property methods that act as setters/getters
- // to an ivar.
- for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
- E = D->propimpl_end(); I!=E; ++I)
- Scan(M, *I);
+ // Now scan the implementation declaration.
+ Scan(M, D);
// Find ivars that are unused.
for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp
new file mode 100644
index 000000000000..33c85d507463
--- /dev/null
+++ b/lib/Analysis/DereferenceChecker.cpp
@@ -0,0 +1,112 @@
+//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker, a builtin check in GRExprEngine that performs
+// checks for null pointers at loads and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *NullDerefChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ Loc *LV = dyn_cast<Loc>(&V);
+
+ // If the value is not a location, don't touch the node.
+ if (!LV)
+ return Pred;
+
+ const GRState *NotNullState = state->Assume(*LV, true);
+ const GRState *NullState = state->Assume(*LV, false);
+
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ // The explicit NULL case.
+ if (NullState) {
+ // Use the GDM to mark in the state what lval was null.
+ const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
+ NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
+
+ ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
+ ProgramPoint::PostNullCheckFailedKind);
+ if (N) {
+ N->markAsSink();
+
+ if (!NotNullState) { // Explicit null case.
+ if (!BT)
+ BT = new BuiltinBug(NULL, "Null dereference",
+ "Dereference of null pointer");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+
+ BR.EmitReport(R);
+
+ return 0;
+ } else // Implicit null case.
+ ImplicitNullDerefNodes.push_back(N);
+ }
+ }
+
+ if (!NotNullState)
+ return 0;
+
+ return Builder.generateNode(S, NotNullState, Pred,
+ ProgramPoint::PostLocationChecksSucceedKind);
+}
+
+
+void *UndefDerefChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S,
+ ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (V.isUndef()) {
+ ExplodedNode *N = Builder.generateNode(S, state, Pred,
+ ProgramPoint::PostUndefLocationCheckFailedKind);
+ if (N) {
+ N->markAsSink();
+
+ if (!BT)
+ BT = new BuiltinBug(0, "Undefined dereference",
+ "Dereference of undefined pointer value");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+ BR.EmitReport(R);
+ }
+ return 0;
+ }
+
+ return Pred;
+}
+
diff --git a/lib/Analysis/DivZeroChecker.cpp b/lib/Analysis/DivZeroChecker.cpp
new file mode 100644
index 000000000000..9c2359f3b075
--- /dev/null
+++ b/lib/Analysis/DivZeroChecker.cpp
@@ -0,0 +1,70 @@
+//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+
+using namespace clang;
+
+void *DivZeroChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ BinaryOperator::Opcode Op = B->getOpcode();
+ if (Op != BinaryOperator::Div &&
+ Op != BinaryOperator::Rem &&
+ Op != BinaryOperator::DivAssign &&
+ Op != BinaryOperator::RemAssign)
+ return;
+
+ if (!B->getRHS()->getType()->isIntegerType() ||
+ !B->getRHS()->getType()->isScalarType())
+ return;
+
+ SVal Denom = C.getState()->getSVal(B->getRHS());
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
+
+ // Divide-by-undefined handled in the generic checking for uses of
+ // undefined values.
+ if (!DV)
+ return;
+
+ // Check for divide by zero.
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotZero, *stateZero;
+ llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
+
+ if (stateZero && !stateNotZero) {
+ if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
+ if (!BT)
+ BT = new BuiltinBug(0, "Division by zero");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDenomExpr(N));
+
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ // If we get here, then the denom should not be zero. We abandon the implicit
+ // zero denom case for now.
+ if (stateNotZero != C.getState())
+ C.addTransition(C.GenerateNode(B, stateNotZero));
+}
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index ea0255ded8a9..c71882e4d888 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -25,6 +25,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/StringSwitch.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
@@ -117,17 +118,18 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
- for (std::vector<Checker*>::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
-
- ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
: (PrevSet == &Tmp) ? &Src : &Tmp;
+
CurrSet->clear();
- Checker *checker = *I;
+ void *tag = I->first;
+ Checker *checker = I->second;
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, isPrevisit);
+ checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit);
// Update which NodeSet is the current one.
PrevSet = CurrSet;
@@ -137,6 +139,41 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
// automatically.
}
+// FIXME: This is largely copy-paste from CheckerVisit(). Need to
+// unify.
+void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src,
+ SVal location, SVal val, bool isPrevisit) {
+
+ if (Checkers.empty()) {
+ Dst = Src;
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ : (PrevSet == &Tmp) ? &Src : &Tmp;
+
+ CurrSet->clear();
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, S, *NI, tag, location,
+ val, isPrevisit);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+
+ // Don't autotransition. The CheckerContext objects should do this
+ // automatically.
+}
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
@@ -165,9 +202,8 @@ GRExprEngine::GRExprEngine(AnalysisManager &mgr)
GRExprEngine::~GRExprEngine() {
BR.FlushReports();
delete [] NSExceptionInstanceRaiseSelectors;
- for (std::vector<Checker*>::iterator I=Checkers.begin(), E=Checkers.end();
- I!=E; ++I)
- delete *I;
+ for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ delete I->second;
}
//===----------------------------------------------------------------------===//
@@ -177,7 +213,7 @@ GRExprEngine::~GRExprEngine() {
void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) {
StateMgr.TF = tf;
- tf->RegisterChecks(getBugReporter());
+ tf->RegisterChecks(*this);
tf->RegisterPrinters(getStateManager().Printers);
}
@@ -369,11 +405,11 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
if (AMgr.shouldEagerlyAssume() && (B->isRelationalOp() || B->isEqualityOp())) {
ExplodedNodeSet Tmp;
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
}
else
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
break;
}
@@ -395,7 +431,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
}
case Stmt::CompoundAssignOperatorClass:
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
break;
case Stmt::CompoundLiteralExprClass:
@@ -409,7 +445,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
}
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
break;
@@ -522,7 +557,6 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return;
@@ -565,6 +599,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
}
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ VisitBinaryOperator(cast<BinaryOperator>(Ex), Pred, Dst, true);
+ return;
+
default:
// Arbitrary subexpressions can return aggregate temporaries that
// can be used in a lvalue context. We need to enhance our support
@@ -1078,8 +1117,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
SVal L = state->getLValue(Field, state->getSVal(Base));
if (asLValue)
- MakeNode(Dst, M, *I, state->BindExpr(M, L),
- ProgramPoint::PostLValueKind);
+ MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, M, *I, state, L);
}
@@ -1087,30 +1125,52 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+ const GRState* state, SVal location, SVal Val,
+ bool atDeclInit) {
+
+
+ // Do a previsit of the bind.
+ ExplodedNodeSet CheckedSet, Src;
+ Src.Add(Pred);
+ CheckerVisitBind(Ex, CheckedSet, Src, location, Val, true);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I!=E; ++I) {
+
+ if (Pred != *I)
+ state = GetState(*I);
+
+ const GRState* newState = 0;
- const GRState* newState = 0;
+ if (atDeclInit) {
+ const VarRegion *VR =
+ cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
- if (location.isUnknown()) {
- // We know that the new state will be the same as the old state since
- // the location of the binding is "unknown". Consequently, there
- // is no reason to just create a new node.
- newState = state;
- }
- else {
- // We are binding to a value other than 'unknown'. Perform the binding
- // using the StoreManager.
- newState = state->bindLoc(cast<Loc>(location), Val);
- }
+ newState = state->bindDecl(VR, Val);
+ }
+ else {
+ if (location.isUnknown()) {
+ // We know that the new state will be the same as the old state since
+ // the location of the binding is "unknown". Consequently, there
+ // is no reason to just create a new node.
+ newState = state;
+ }
+ else {
+ // We are binding to a value other than 'unknown'. Perform the binding
+ // using the StoreManager.
+ newState = state->bindLoc(cast<Loc>(location), Val);
+ }
+ }
- // The next thing to do is check if the GRTransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc object
- // doesn't do anything, just auto-propagate the current state.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, Pred, newState, Ex,
- newState != state);
+ // The next thing to do is check if the GRTransferFuncs object wants to
+ // update the state based on the new binding. If the GRTransferFunc object
+ // doesn't do anything, just auto-propagate the current state.
+ GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, Ex,
+ newState != state);
- getTF().EvalBind(BuilderRef, location, Val);
+ getTF().EvalBind(BuilderRef, location, Val);
+ }
}
/// EvalStore - Handle the semantics of a store via an assignment.
@@ -1189,58 +1249,18 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
SaveAndRestore<const void*> OldTag(Builder->Tag);
Builder->Tag = tag;
- // Check for loads/stores from/to undefined values.
- if (location.isUndef()) {
- ExplodedNode* N =
- Builder->generateNode(Ex, state, Pred,
- ProgramPoint::PostUndefLocationCheckFailedKind);
-
- if (N) {
- N->markAsSink();
- UndefDeref.insert(N);
- }
-
- return 0;
- }
-
- // Check for loads/stores from/to unknown locations. Treat as No-Ops.
- if (location.isUnknown())
+ if (location.isUnknown() || Checkers.empty())
return Pred;
- // During a load, one of two possible situations arise:
- // (1) A crash, because the location (pointer) was NULL.
- // (2) The location (pointer) is not NULL, and the dereference works.
- //
- // We add these assumptions.
-
- Loc LV = cast<Loc>(location);
-
- // "Assume" that the pointer is not NULL.
- const GRState *StNotNull = state->Assume(LV, true);
-
- // "Assume" that the pointer is NULL.
- const GRState *StNull = state->Assume(LV, false);
-
- if (StNull) {
- // Use the Generic Data Map to mark in the state what lval was null.
- const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV);
- StNull = StNull->set<GRState::NullDerefTag>(PersistentLV);
-
- // We don't use "MakeNode" here because the node will be a sink
- // and we have no intention of processing it later.
- ExplodedNode* NullNode =
- Builder->generateNode(Ex, StNull, Pred,
- ProgramPoint::PostNullCheckFailedKind);
-
- if (NullNode) {
- NullNode->markAsSink();
- if (StNotNull) ImplicitNullDeref.insert(NullNode);
- else ExplicitNullDeref.insert(NullNode);
- }
+
+ for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ {
+ Pred = I->second->CheckLocation(Ex, Pred, state, location, *this);
+ if (!Pred)
+ break;
}
-
- if (!StNotNull)
- return NULL;
+
+ return Pred;
// FIXME: Temporarily disable out-of-bounds checking until we make
// the logic reflect recent changes to CastRegion and friends.
@@ -1283,10 +1303,6 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
}
}
#endif
-
- // Generate a new node indicating the checks succeed.
- return Builder->generateNode(Ex, StNotNull, Pred,
- ProgramPoint::PostLocationChecksSucceedKind);
}
//===----------------------------------------------------------------------===//
@@ -1445,75 +1461,30 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
// HACK: Some functions are not marked noreturn, and don't return.
// Here are a few hardwired ones. If this takes too long, we can
// potentially cache these results.
- const char* s = FD->getIdentifier()->getNameStart();
-
- switch (FD->getIdentifier()->getLength()) {
- default:
- break;
-
- case 4:
- if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
- break;
-
- case 5:
- if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
- else if (!memcmp(s, "error", 5)) {
- if (CE->getNumArgs() > 0) {
- SVal X = state->getSVal(*CE->arg_begin());
- // FIXME: use Assume to inspect the possible symbolic value of
- // X. Also check the specific signature of error().
- nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
- if (CI && CI->getValue() != 0)
- Builder->BuildSinks = true;
- }
- }
- break;
-
- case 6:
- if (!memcmp(s, "Assert", 6)) {
- Builder->BuildSinks = true;
- break;
- }
-
- // FIXME: This is just a wrapper around throwing an exception.
- // Eventually inter-procedural analysis should handle this easily.
- if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
-
- break;
-
- case 7:
- if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
- break;
-
- case 8:
- if (!memcmp(s ,"db_error", 8) ||
- !memcmp(s, "__assert", 8))
- Builder->BuildSinks = true;
- break;
-
- case 12:
- if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
- break;
-
- case 13:
- if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
- break;
-
- case 14:
- if (!memcmp(s, "dtrace_assfail", 14) ||
- !memcmp(s, "yy_fatal_error", 14))
- Builder->BuildSinks = true;
- break;
-
- case 26:
- if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
- !memcmp(s, "_DTAssertionFailureHandler", 26) ||
- !memcmp(s, "_TSAssertionFailureHandler", 26))
- Builder->BuildSinks = true;
-
- break;
- }
-
+ using llvm::StringRef;
+ bool BuildSinks
+ = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
+ .Case("exit", true)
+ .Case("panic", true)
+ .Case("error", true)
+ .Case("Assert", true)
+ // FIXME: This is just a wrapper around throwing an exception.
+ // Eventually inter-procedural analysis should handle this easily.
+ .Case("ziperr", true)
+ .Case("assfail", true)
+ .Case("db_error", true)
+ .Case("__assert", true)
+ .Case("__assert_rtn", true)
+ .Case("__assert_fail", true)
+ .Case("dtrace_assfail", true)
+ .Case("yy_fatal_error", true)
+ .Case("_XCAssertionFailureHandler", true)
+ .Case("_DTAssertionFailureHandler", true)
+ .Case("_TSAssertionFailureHandler", true)
+ .Default(false);
+
+ if (BuildSinks)
+ Builder->BuildSinks = true;
}
}
@@ -2042,24 +2013,27 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
}
}
+ // Handle previsits checks.
+ ExplodedNodeSet Src, DstTmp;
+ Src.Add(Pred);
+ CheckerVisit(ME, DstTmp, Src, true);
+
// Check if we raise an exception. For now treat these as sinks. Eventually
// we will want to handle exceptions properly.
-
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-
if (RaisesException)
Builder->BuildSinks = true;
// Dispatch to plug-in transfer function.
-
unsigned size = Dst.size();
SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- EvalObjCMessageExpr(Dst, ME, Pred);
+
+ for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
+ DI!=DE; ++DI)
+ EvalObjCMessageExpr(Dst, ME, *DI);
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
-
if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
MakeNode(Dst, ME, Pred, state);
}
@@ -2141,45 +2115,25 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Tmp.Add(Pred);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- unsigned Count = Builder->getCurrentBlockCount();
-
- // Check if 'VD' is a VLA and if so check if has a non-zero size.
- QualType T = getContext().getCanonicalType(VD->getType());
- if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
- // FIXME: Handle multi-dimensional VLAs.
-
- Expr* SE = VLA->getSizeExpr();
- SVal Size_untested = state->getSVal(SE);
-
- if (Size_untested.isUndef()) {
- if (ExplodedNode* N = Builder->generateNode(DS, state, Pred)) {
- N->markAsSink();
- ExplicitBadSizedVLA.insert(N);
- }
- continue;
- }
-
- DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Size_untested);
- const GRState *zeroState = state->Assume(Size, false);
- state = state->Assume(Size, true);
+ ExplodedNode *N = *I;
+ const GRState *state;
+
+ for (CheckersOrdered::iterator CI = Checkers.begin(), CE = Checkers.end();
+ CI != CE; ++CI) {
+ state = GetState(N);
+ N = CI->second->CheckType(getContext().getCanonicalType(VD->getType()),
+ N, state, DS, *this);
+ if (!N)
+ break;
+ }
- if (zeroState) {
- if (ExplodedNode* N = Builder->generateNode(DS, zeroState, Pred)) {
- N->markAsSink();
- if (state)
- ImplicitBadSizedVLA.insert(N);
- else
- ExplicitBadSizedVLA.insert(N);
- }
- }
+ if (!N)
+ continue;
- if (!state)
- continue;
- }
+ state = GetState(N);
// Decls without InitExpr are not initialized explicitly.
- const LocationContext *LC = (*I)->getLocationContext();
+ const LocationContext *LC = N->getLocationContext();
if (InitEx) {
SVal InitVal = state->getSVal(InitEx);
@@ -2189,20 +2143,15 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
// UnknownVal.
if (InitVal.isUnknown() ||
!getConstraintManager().canReasonAbout(InitVal)) {
- InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Count);
+ InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx,
+ Builder->getCurrentBlockCount());
}
-
- state = state->bindDecl(VD, LC, InitVal);
-
- // The next thing to do is check if the GRTransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc
- // object doesn't do anything, just auto-propagate the current state.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, state, DS,true);
- getTF().EvalBind(BuilderRef, loc::MemRegionVal(state->getRegion(VD, LC)),
- InitVal);
+
+ EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)),
+ InitVal, true);
}
else {
- state = state->bindDeclWithNoInit(VD, LC);
+ state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
MakeNode(Dst, DS, *I, state);
}
}
@@ -2752,7 +2701,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, ExplodedNode* Pred,
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
+ ExplodedNodeSet& Dst, bool asLValue) {
ExplodedNodeSet Tmp1;
Expr* LHS = B->getLHS()->IgnoreParens();
@@ -2798,10 +2747,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
unsigned Count = Builder->getCurrentBlockCount();
RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
}
-
+
+ SVal ExprVal = asLValue ? LeftV : RightV;
+
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
- EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV);
+ EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV);
continue;
}
@@ -2930,6 +2881,15 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
}
//===----------------------------------------------------------------------===//
+// Checker registration/lookup.
+//===----------------------------------------------------------------------===//
+
+Checker *GRExprEngine::lookupChecker(void *tag) const {
+ CheckerMap::iterator I = CheckerM.find(tag);
+ return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
+}
+
+//===----------------------------------------------------------------------===//
// Visualization.
//===----------------------------------------------------------------------===//
@@ -2941,7 +2901,8 @@ namespace llvm {
template<>
struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
public DefaultDOTGraphTraits {
-
+ // FIXME: Since we do not cache error nodes in GRExprEngine now, this does not
+ // work.
static std::string getNodeAttributes(const ExplodedNode* N, void*) {
if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index da24192c9d5a..695f0b02e597 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -15,6 +15,13 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
@@ -40,10 +47,8 @@ ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
//===----------------------------------------------------------------------===//
// Bug Descriptions.
//===----------------------------------------------------------------------===//
-
-namespace {
-
-class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
+namespace clang {
+class BuiltinBugReport : public RangedBugReport {
public:
BuiltinBugReport(BugType& bt, const char* desc,
ExplodedNode *n)
@@ -57,30 +62,10 @@ public:
const ExplodedNode* N);
};
-class VISIBILITY_HIDDEN BuiltinBug : public BugType {
- GRExprEngine &Eng;
-protected:
- const std::string desc;
-public:
- BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
- : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
-
- BuiltinBug(GRExprEngine *eng, const char* n)
- : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
-
- const std::string &getDescription() const { return desc; }
-
- virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
-
- void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
-
- virtual void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {}
-
- template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
-};
-
+void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode* N) {
+ static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
+}
template <typename ITER>
void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
@@ -88,27 +73,6 @@ void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
GetNode(I)));
}
-void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N) {
- static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
-}
-
-class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
-public:
- NullDeref(GRExprEngine* eng)
- : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
public:
NilReceiverStructRet(GRExprEngine* eng) :
@@ -175,34 +139,6 @@ public:
}
};
-class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
-public:
- UndefinedDeref(GRExprEngine* eng)
- : BuiltinBug(eng,"Dereference of undefined pointer value") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
- }
-};
-
-class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
-public:
- DivZero(GRExprEngine* eng = 0)
- : BuiltinBug(eng,"Division by zero") {}
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
public:
UndefResult(GRExprEngine* eng)
@@ -279,20 +215,6 @@ public:
}
};
-class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
-public:
- BadCall(GRExprEngine *eng = 0)
- : BuiltinBug(eng, "Invalid function call",
- "Called function pointer is a null or undefined pointer value") {}
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
- }
-};
-
-
class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
const Stmt *Arg;
public:
@@ -528,276 +450,8 @@ public:
}
};
-class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
-public:
- BadSizeVLA(GRExprEngine* eng) :
- BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::ErrorNodes::iterator
- I = Eng.ExplicitBadSizedVLA.begin(),
- E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
-
- // Determine whether this was a 'zero-sized' VLA or a VLA with an
- // undefined size.
- ExplodedNode* N = *I;
- PostStmt PS = cast<PostStmt>(N->getLocation());
- const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
- VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
- QualType T = Eng.getContext().getCanonicalType(VD->getType());
- VariableArrayType* VT = cast<VariableArrayType>(T);
- Expr* SizeExpr = VT->getSizeExpr();
-
- std::string buf;
- llvm::raw_string_ostream os(buf);
- os << "The expression used to specify the number of elements in the "
- "variable-length array (VLA) '"
- << VD->getNameAsString() << "' evaluates to ";
-
- bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
-
- if (isUndefined)
- os << "an undefined or garbage value.";
- else
- os << "0. VLAs with no elements have undefined behavior.";
-
- std::string shortBuf;
- llvm::raw_string_ostream os_short(shortBuf);
- os_short << "Variable-length array '" << VD->getNameAsString() << "' "
- << (isUndefined ? "garbage value for array size"
- : "has zero elements (undefined behavior)");
-
- ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
- os.str().c_str(), N, SizeExpr);
-
- report->addRange(SizeExpr->getSourceRange());
- BR.EmitReport(report);
- }
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
- N);
- }
-};
-
-//===----------------------------------------------------------------------===//
-// __attribute__(nonnull) checking
-
-class VISIBILITY_HIDDEN CheckAttrNonNull :
- public CheckerVisitor<CheckAttrNonNull> {
-
- BugType *BT;
-
-public:
- CheckAttrNonNull() : BT(0) {}
- ~CheckAttrNonNull() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- const GRState *state = C.getState();
- const GRState *originalState = state;
-
- // Check if the callee has a 'nonnull' attribute.
- SVal X = state->getSVal(CE->getCallee());
-
- const FunctionDecl* FD = X.getAsFunctionDecl();
- if (!FD)
- return;
+} // end clang namespace
- const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
- if (!Att)
- return;
-
- // Iterate through the arguments of CE and check them for null.
- unsigned idx = 0;
-
- for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
- ++I, ++idx) {
-
- if (!Att->isNonNull(idx))
- continue;
-
- const SVal &V = state->getSVal(*I);
- const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
-
- if (!DV)
- continue;
-
- ConstraintManager &CM = C.getConstraintManager();
- const GRState *stateNotNull, *stateNull;
- llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
-
- if (stateNull && !stateNotNull) {
- // Generate an error node. Check for a null node in case
- // we cache out.
- if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
-
- // Lazily allocate the BugType object if it hasn't already been
- // created. Ownership is transferred to the BugReporter object once
- // the BugReport is passed to 'EmitWarning'.
- if (!BT)
- BT = new BugType("Argument with 'nonnull' attribute passed null",
- "API");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT,
- "Null pointer passed as an argument to a "
- "'nonnull' parameter", errorNode);
-
- // Highlight the range of the argument that was null.
- const Expr *arg = *I;
- R->addRange(arg->getSourceRange());
- R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
-
- // Emit the bug report.
- C.EmitReport(R);
- }
-
- // Always return. Either we cached out or we just emitted an error.
- return;
- }
-
- // If a pointer value passed the check we should assume that it is
- // indeed not null from this point forward.
- assert(stateNotNull);
- state = stateNotNull;
- }
-
- // If we reach here all of the arguments passed the nonnull check.
- // If 'state' has been updated generated a new node.
- if (state != originalState)
- C.addTransition(C.GenerateNode(CE, state));
- }
-};
-} // end anonymous namespace
-
-// Undefined arguments checking.
-namespace {
-class VISIBILITY_HIDDEN CheckUndefinedArg
- : public CheckerVisitor<CheckUndefinedArg> {
-
- BadArg *BT;
-
-public:
- CheckUndefinedArg() : BT(0) {}
- ~CheckUndefinedArg() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
- for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
- I != E; ++I) {
- if (C.getState()->getSVal(*I).isUndef()) {
- if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
- if (!BT)
- BT = new BadArg();
- // Generate a report for this bug.
- ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
- ErrorNode, *I);
- Report->addRange((*I)->getSourceRange());
- C.EmitReport(Report);
- }
- }
- }
-}
-
-class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
- BadCall *BT;
-
-public:
- CheckBadCall() : BT(0) {}
- ~CheckBadCall() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- const Expr *Callee = CE->getCallee()->IgnoreParens();
- SVal L = C.getState()->getSVal(Callee);
-
- if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
- if (ExplodedNode *N = C.GenerateNode(CE, true)) {
- if (!BT)
- BT = new BadCall();
- C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
- }
- }
-}
-
-class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
- DivZero *BT;
-public:
- CheckDivZero() : BT(0) {}
- ~CheckDivZero() {}
-
- const void *getTag() {
- static int x;
- return &x;
- }
-
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
-};
-
-void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
- BinaryOperator::Opcode Op = B->getOpcode();
- if (Op != BinaryOperator::Div &&
- Op != BinaryOperator::Rem &&
- Op != BinaryOperator::DivAssign &&
- Op != BinaryOperator::RemAssign)
- return;
-
- if (!B->getRHS()->getType()->isIntegerType() ||
- !B->getRHS()->getType()->isScalarType())
- return;
-
- SVal Denom = C.getState()->getSVal(B->getRHS());
- const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
-
- // Divide-by-undefined handled in the generic checking for uses of
- // undefined values.
- if (!DV)
- return;
-
- // Check for divide by zero.
- ConstraintManager &CM = C.getConstraintManager();
- const GRState *stateNotZero, *stateZero;
- llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
-
- if (stateZero && !stateNotZero) {
- if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
- if (!BT)
- BT = new DivZero();
-
- C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
- }
- return;
- }
-
- // If we get here, then the denom should not be zero. We abandon the implicit
- // zero denom case for now.
- if (stateNotZero != C.getState())
- C.addTransition(C.GenerateNode(B, stateNotZero));
-}
-}
//===----------------------------------------------------------------------===//
// Check registration.
//===----------------------------------------------------------------------===//
@@ -808,8 +462,6 @@ void GRExprEngine::RegisterInternalChecks() {
// create BugReports on-the-fly but instead wait until GRExprEngine finishes
// analyzing a function. Generation of BugReport objects is done via a call
// to 'FlushReports' from BugReporter.
- BR.Register(new NullDeref(this));
- BR.Register(new UndefinedDeref(this));
BR.Register(new UndefBranch(this));
BR.Register(new UndefResult(this));
BR.Register(new RetStack(this));
@@ -817,7 +469,6 @@ void GRExprEngine::RegisterInternalChecks() {
BR.Register(new BadMsgExprArg(this));
BR.Register(new BadReceiver(this));
BR.Register(new OutOfBoundMemoryAccess(this));
- BR.Register(new BadSizeVLA(this));
BR.Register(new NilReceiverStructRet(this));
BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
@@ -826,8 +477,13 @@ void GRExprEngine::RegisterInternalChecks() {
// their associated BugType will get registered with the BugReporter
// automatically. Note that the check itself is owned by the GRExprEngine
// object.
- registerCheck(new CheckAttrNonNull());
- registerCheck(new CheckUndefinedArg());
- registerCheck(new CheckBadCall());
- registerCheck(new CheckDivZero());
+ registerCheck(new AttrNonNullChecker());
+ registerCheck(new UndefinedArgChecker());
+ registerCheck(new UndefinedAssignmentChecker());
+ registerCheck(new BadCallChecker());
+ registerCheck(new DivZeroChecker());
+ registerCheck(new UndefDerefChecker());
+ registerCheck(new NullDerefChecker());
+ registerCheck(new UndefSizedVLAChecker());
+ registerCheck(new ZeroSizedVLAChecker());
}
diff --git a/lib/Analysis/NSAutoreleasePoolChecker.cpp b/lib/Analysis/NSAutoreleasePoolChecker.cpp
new file mode 100644
index 000000000000..e0a8d0dc5f73
--- /dev/null
+++ b/lib/Analysis/NSAutoreleasePoolChecker.cpp
@@ -0,0 +1,84 @@
+//=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a NSAutoreleasePoolChecker, a small checker that warns
+// about subpar uses of NSAutoreleasePool. Note that while the check itself
+// (in it's current form) could be written as a flow-insensitive check, in
+// can be potentially enhanced in the future with flow-sensitive information.
+// It is also a good example of the CheckerVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "BasicObjCFoundationChecks.h"
+#include "llvm/Support/Compiler.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN NSAutoreleasePoolChecker
+ : public CheckerVisitor<NSAutoreleasePoolChecker> {
+
+ Selector releaseS;
+
+public:
+ NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
+
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+
+ void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+};
+
+} // end anonymous namespace
+
+
+void clang::RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng) {
+ ASTContext &Ctx = Eng.getContext();
+ if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
+ Ctx)));
+ }
+}
+
+void
+NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
+ const ObjCMessageExpr *ME) {
+
+ const Expr *receiver = ME->getReceiver();
+ if (!receiver)
+ return;
+
+ // FIXME: Enhance with value-tracking information instead of consulting
+ // the type of the expression.
+ const ObjCObjectPointerType* PT =
+ receiver->getType()->getAs<ObjCObjectPointerType>();
+ const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
+ if (!OD)
+ return;
+ if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+ return;
+
+ // Sending 'release' message?
+ if (ME->getSelector() != releaseS)
+ return;
+
+ SourceRange R = ME->getSourceRange();
+
+ C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
+ "API Upgrade (Apple)",
+ "Use -drain instead of -release when using NSAutoreleasePool "
+ "and garbage collection", ME->getLocStart(), &R, 1);
+}
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/NSErrorChecker.cpp
index 8086da588264..307686ff57b3 100644
--- a/lib/Analysis/CheckNSError.cpp
+++ b/lib/Analysis/NSErrorChecker.cpp
@@ -1,4 +1,4 @@
-//=- CheckNSError.cpp - Coding conventions for uses of NSError ---*- C++ -*-==//
+//=- NSErrorCheckerer.cpp - Coding conventions for uses of NSError -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
#include "BasicObjCFoundationChecks.h"
#include "llvm/Support/Compiler.h"
#include "clang/AST/DeclObjC.h"
@@ -27,7 +28,7 @@
using namespace clang;
namespace {
-class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
+class VISIBILITY_HIDDEN NSErrorChecker : public BugType {
const Decl &CodeDecl;
const bool isNSErrorWarning;
IdentifierInfo * const II;
@@ -48,7 +49,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl);
public:
- NSErrorCheck(const Decl &D, bool isNSError, GRExprEngine& eng)
+ NSErrorChecker(const Decl &D, bool isNSError, GRExprEngine& eng)
: BugType(isNSError ? "NSError** null dereference"
: "CFErrorRef* null dereference",
"Coding conventions (Apple)"),
@@ -64,11 +65,11 @@ public:
void clang::RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng,
const Decl &D) {
- BR.Register(new NSErrorCheck(D, true, Eng));
- BR.Register(new NSErrorCheck(D, false, Eng));
+ BR.Register(new NSErrorChecker(D, true, Eng));
+ BR.Register(new NSErrorChecker(D, false, Eng));
}
-void NSErrorCheck::FlushReports(BugReporter& BR) {
+void NSErrorChecker::FlushReports(BugReporter& BR) {
// Get the analysis engine and the exploded analysis graph.
ExplodedGraph& G = Eng.getGraph();
@@ -99,7 +100,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) {
}
}
-void NSErrorCheck::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
+void NSErrorChecker::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -121,7 +122,7 @@ void NSErrorCheck::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
}
void
-NSErrorCheck::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
+NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
ResultTy = M.getResultType();
@@ -140,7 +141,7 @@ NSErrorCheck::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
}
void
-NSErrorCheck::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
+NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
ResultTy = F.getResultType();
@@ -159,7 +160,7 @@ NSErrorCheck::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
}
-bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
+bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) {
const PointerType* PPT = ArgTy->getAs<PointerType>();
if (!PPT)
@@ -180,7 +181,7 @@ bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
return false;
}
-bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
+bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) {
const PointerType* PPT = ArgTy->getAs<PointerType>();
if (!PPT) return false;
@@ -191,7 +192,7 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
return TT->getDecl()->getIdentifier() == II;
}
-void NSErrorCheck::CheckParamDeref(const VarDecl *Param,
+void NSErrorChecker::CheckParamDeref(const VarDecl *Param,
const LocationContext *LC,
const GRState *rootState,
BugReporter& BR) {
@@ -208,8 +209,10 @@ void NSErrorCheck::CheckParamDeref(const VarDecl *Param,
return;
// Iterate over the implicit-null dereferences.
- for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
- E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
+ NullDerefChecker *Checker = Eng.getChecker<NullDerefChecker>();
+ assert(Checker && "NullDerefChecker not exist.");
+ for (NullDerefChecker::iterator I = Checker->implicit_nodes_begin(),
+ E = Checker->implicit_nodes_end(); I != E; ++I) {
const GRState *state = (*I)->getState();
const SVal* X = state->get<GRState::NullDerefTag>();
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 780772a6f129..dbf8c42d273e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -275,11 +275,11 @@ public:
const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL, SVal V);
- const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
- const LocationContext *LC, SVal InitVal);
+ const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
+ SVal InitVal);
- const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl*,
- const LocationContext *) {
+ const GRState *BindDeclWithNoInit(const GRState *state,
+ const VarRegion *) {
return state;
}
@@ -1409,12 +1409,10 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
}
const GRState *RegionStoreManager::BindDecl(const GRState *ST,
- const VarDecl *VD,
- const LocationContext *LC,
+ const VarRegion *VR,
SVal InitVal) {
- QualType T = VD->getType();
- VarRegion* VR = MRMgr.getVarRegion(VD, LC);
+ QualType T = VR->getDecl()->getType();
if (T->isArrayType())
return BindArray(ST, VR, InitVal);
@@ -1630,6 +1628,8 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// Process the "intermediate" roots to find if they are referenced by
// real roots.
llvm::SmallVector<RBDNode, 10> WorkList;
+ llvm::SmallVector<RBDNode, 10> Postponed;
+
llvm::DenseSet<const MemRegion*> IntermediateVisited;
while (!IntermediateRoots.empty()) {
@@ -1647,8 +1647,11 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
}
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
- if (SymReaper.isLive(SR->getSymbol()))
- WorkList.push_back(std::make_pair(&state, SR));
+ llvm::SmallVectorImpl<RBDNode> &Q =
+ SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
+
+ Q.push_back(std::make_pair(&state, SR));
+
continue;
}
@@ -1667,6 +1670,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
llvm::DenseSet<RBDNode> Visited;
+tryAgain:
while (!WorkList.empty()) {
RBDNode N = WorkList.back();
WorkList.pop_back();
@@ -1740,6 +1744,21 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
}
}
+ // See if any postponed SymbolicRegions are actually live now, after
+ // having done a scan.
+ for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
+ E = Postponed.end() ; I != E ; ++I) {
+ if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
+ if (SymReaper.isLive(SR->getSymbol())) {
+ WorkList.push_back(*I);
+ I->second = NULL;
+ }
+ }
+ }
+
+ if (!WorkList.empty())
+ goto tryAgain;
+
// We have now scanned the store, marking reachable regions and symbols
// as live. We now remove all the regions that are dead from the store
// as well as update DSymbols with the set symbols that are now dead.
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp
new file mode 100644
index 000000000000..a229f55ff6d9
--- /dev/null
+++ b/lib/Analysis/UndefinedArgChecker.cpp
@@ -0,0 +1,43 @@
+//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for undefined arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedArgChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE){
+ for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+ I != E; ++I) {
+ if (C.getState()->getSVal(*I).isUndef()) {
+ if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+ if (!BT)
+ BT = new BugType("Pass-by-value argument in function call is "
+ "undefined", "Logic error");
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(),
+ N);
+ R->addRange((*I)->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
new file mode 100644
index 000000000000..c5b2401f47ce
--- /dev/null
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -0,0 +1,61 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedAssignmentChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *S,
+ SVal location,
+ SVal val) {
+ if (!val.isUndef())
+ return;
+
+ ExplodedNode *N = C.GenerateNode(S, true);
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BugType("Assigned value is garbage or undefined",
+ "Logic error");
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ const Expr *ex = 0;
+
+ // FIXME: This check needs to be done on the expression doing the
+ // assignment, not the "store" expression.
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ ex = B->getRHS();
+ else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ ex = VD->getInit();
+ }
+
+ if (ex) {
+ R->addRange(ex->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ }
+
+ C.EmitReport(R);
+}
+
diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp
new file mode 100644
index 000000000000..76e4477449ed
--- /dev/null
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -0,0 +1,102 @@
+//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
+// performs checks for declaration of VLA of undefined or zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefSizedVLAChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state,
+ Stmt *S, GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+ // FIXME: Handle multi-dimensional VLAs.
+ Expr* SE = VLA->getSizeExpr();
+ SVal Size_untested = state->getSVal(SE);
+
+ if (Size_untested.isUndef()) {
+ if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
+ N->markAsSink();
+ if (!BT)
+ BT = new BugType("Declare variable-length array (VLA) of undefined "
+ "size", "Logic error");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ R->addRange(SE->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ BR.EmitReport(R);
+ }
+ return 0;
+ }
+ }
+ return Pred;
+}
+
+void *ZeroSizedVLAChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S,
+ GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+ // FIXME: Handle multi-dimensional VLAs.
+ Expr* SE = VLA->getSizeExpr();
+ SVal Size_untested = state->getSVal(SE);
+
+ DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
+ // Undefined size is checked in another checker.
+ if (!Size)
+ return Pred;
+
+ const GRState *zeroState = state->Assume(*Size, false);
+ state = state->Assume(*Size, true);
+
+ if (zeroState && !state) {
+ if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
+ N->markAsSink();
+ if (!BT)
+ BT = new BugType("Declare variable-length array (VLA) of zero size",
+ "Logic error");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ R->addRange(SE->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ BR.EmitReport(R);
+ }
+ }
+ if (!state)
+ return 0;
+
+ return Builder.generateNode(S, state, Pred);
+ }
+ else
+ return Pred;
+}
+
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 527ebf965934..1a89acc65af3 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -18,7 +18,7 @@ add_clang_library(clangBasic
# FIXME: This only gets updated when CMake is run, so this revision number
# may be out-of-date!
find_package(Subversion)
-if (Subversion_FOUND)
+if (Subversion_FOUND AND EXISTS "${CLANG_SOURCE_DIR}/.svn")
Subversion_WC_INFO(${CLANG_SOURCE_DIR} CLANG)
set_source_files_properties(Version.cpp
PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${CLANG_WC_REVISION}\"")
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 16aa0c54846a..401e6cba0692 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -381,3 +381,17 @@ SelectorTable::~SelectorTable() {
delete &getSelectorTableImpl(Impl);
}
+const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
+ switch (Operator) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ return 0;
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name: return Spelling;
+#include "clang/Basic/OperatorKinds.def"
+ }
+
+ return 0;
+}
+
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 8f3c777c2004..12caf0c8e512 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -106,9 +106,9 @@ unsigned TargetInfo::getTypeWidth(IntType T) const {
};
}
-/// getTypeSigned - Return whether an integer types is signed. Returns true if
+/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
-bool TargetInfo::getTypeSigned(IntType T) const {
+bool TargetInfo::isTypeSigned(IntType T) const {
switch (T) {
default: assert(0 && "not an integer!");
case SignedShort:
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 66d6824b6f29..f418c5a81c12 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -1533,6 +1533,8 @@ namespace {
Define(Defines, "ram", "__attribute__((address_space(0)))");
Define(Defines, "_section(SectName)",
"__attribute__((section(SectName)))");
+ Define(Defines, "near",
+ "__attribute__((section(\"Address=NEAR\")))");
Define(Defines, "_address(Addr)",
"__attribute__((section(\"Address=\"#Addr)))");
Define(Defines, "_CONFIG(conf)", "asm(\"CONFIG \"#conf)");
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 987cd24e2c8b..c26921969a88 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -199,6 +199,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
}
case Builtin::BI__builtin_object_size: {
+ // FIXME: We're awaiting the llvm intrincis.
+#if 0
+ // We pass this builtin onto the optimizer so that it can
+ // figure out the object size in more complex cases.
+ const llvm::Type *ResType[] = {
+ ConvertType(E->getType())
+ };
+ Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1);
+ return RValue::get(Builder.CreateCall2(F,
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1))));
+#else
// FIXME: Implement. For now we just always fail and pretend we
// don't know the object size.
llvm::APSInt TypeArg = E->getArg(1)->EvaluateAsInt(CGM.getContext());
@@ -207,6 +219,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
bool UseMinimum = TypeArg.getZExtValue() & 2;
return RValue::get(
llvm::ConstantInt::get(ResType, UseMinimum ? 0 : -1LL));
+#endif
}
case Builtin::BI__builtin_prefetch: {
Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index cfa669dc4b6e..3e854ca279b6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -71,16 +71,17 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
const Expr *Init = D.getInit();
QualType T = D.getType();
+ bool isVolatile = getContext().getCanonicalType(T).isVolatileQualified();
if (T->isReferenceType()) {
ErrorUnsupported(Init, "global variable that binds to a reference");
} else if (!hasAggregateLLVMType(T)) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T);
+ EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
} else if (T->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
- EmitAggExpr(Init, DeclPtr, T.isVolatileQualified());
+ EmitAggExpr(Init, DeclPtr, isVolatile);
if (const RecordType *RT = T->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
@@ -95,8 +96,9 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
if (CXXGlobalInits.empty())
return;
- const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- false);
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
// Create our global initialization function.
// FIXME: Should this be tweakable by targets?
@@ -139,18 +141,20 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
// Create the guard variable.
llvm::GlobalValue *GuardV =
- new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), false,
- GV->getLinkage(),
- llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)),
+ new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext),
+ false, GV->getLinkage(),
+ llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)),
GuardVName.str());
// Load the first byte of the guard variable.
- const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+ const llvm::Type *PtrTy
+ = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
"tmp");
// Compare it against 0.
- llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext));
+ llvm::Value *nullValue
+ = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext));
llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
llvm::BasicBlock *InitBlock = createBasicBlock("init");
@@ -163,7 +167,8 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
EmitCXXGlobalVarDeclInit(D, GV);
- Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1),
+ Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext),
+ 1),
Builder.CreateBitCast(GuardV, PtrTy));
EmitBlock(EndBlock);
@@ -591,11 +596,16 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
const CXXConstructExpr *E) {
assert(Dest && "Must have a destination!");
const CXXConstructorDecl *CD = E->getConstructor();
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(E->getType());
// For a copy constructor, even if it is trivial, must fall thru so
// its argument is code-gen'ed.
if (!CD->isCopyConstructor(getContext())) {
+ QualType InitType = E->getType();
+ if (Array)
+ InitType = getContext().getBaseElementType(Array);
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl());
if (RD->hasTrivialConstructor())
return;
}
@@ -606,9 +616,18 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
EmitAggExpr((*i), Dest, false);
return;
}
- // Call the constructor.
- EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
- E->arg_begin(), E->arg_end());
+ if (Array) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(Dest, BasePtr);
+ EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr);
+ }
+ else
+ // Call the constructor.
+ EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
+ E->arg_begin(), E->arg_end());
}
void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
@@ -688,32 +707,39 @@ llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn,
const CXXMethodDecl *MD,
bool Extern, int64_t nv,
int64_t v) {
- QualType R = MD->getType()->getAs<FunctionType>()->getResultType();
+ return GenerateCovariantThunk(Fn, MD, Extern, nv, v, 0, 0);
+}
- FunctionArgList Args;
- ImplicitParamDecl *ThisDecl =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
- MD->getThisType(getContext()));
- Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
- for (FunctionDecl::param_const_iterator i = MD->param_begin(),
- e = MD->param_end();
- i != e; ++i) {
- ParmVarDecl *D = *i;
- Args.push_back(std::make_pair(D, D->getType()));
+llvm::Value *CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, int64_t nv,
+ int64_t v) {
+ llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
+ 0);
+ const llvm::Type *OrigTy = V->getType();
+ if (nv) {
+ // Do the non-virtual adjustment
+ V = Builder.CreateBitCast(V, Ptr8Ty);
+ V = Builder.CreateConstInBoundsGEP1_64(V, nv);
+ V = Builder.CreateBitCast(V, OrigTy);
}
- IdentifierInfo *II
- = &CGM.getContext().Idents.get("__thunk_named_foo_");
- FunctionDecl *FD = FunctionDecl::Create(getContext(),
- getContext().getTranslationUnitDecl(),
- SourceLocation(), II, R, 0,
- Extern
- ? FunctionDecl::Extern
- : FunctionDecl::Static,
- false, true);
- StartFunction(FD, R, Fn, Args, SourceLocation());
- // FIXME: generate body
- FinishFunction();
- return Fn;
+ if (v) {
+ // Do the virtual this adjustment
+ const llvm::Type *PtrDiffTy =
+ ConvertType(getContext().getPointerDiffType());
+ llvm::Type *PtrPtr8Ty, *PtrPtrDiffTy;
+ PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
+ PtrPtrDiffTy = llvm::PointerType::get(PtrDiffTy, 0);
+ llvm::Value *ThisVal = Builder.CreateBitCast(V, Ptr8Ty);
+ V = Builder.CreateBitCast(V, PtrPtrDiffTy->getPointerTo());
+ V = Builder.CreateLoad(V, "vtable");
+ llvm::Value *VTablePtr = V;
+ assert(v % (LLVMPointerWidth/8) == 0 && "vtable entry unaligned");
+ v /= LLVMPointerWidth/8;
+ V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, v);
+ V = Builder.CreateLoad(V);
+ V = Builder.CreateGEP(ThisVal, V);
+ V = Builder.CreateBitCast(V, OrigTy);
+ }
+ return V;
}
llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
@@ -723,7 +749,7 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
int64_t v_t,
int64_t nv_r,
int64_t v_r) {
- QualType R = MD->getType()->getAs<FunctionType>()->getResultType();
+ QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
FunctionArgList Args;
ImplicitParamDecl *ThisDecl =
@@ -740,13 +766,57 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
= &CGM.getContext().Idents.get("__thunk_named_foo_");
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
- SourceLocation(), II, R, 0,
+ SourceLocation(), II, ResultType, 0,
Extern
? FunctionDecl::Extern
: FunctionDecl::Static,
false, true);
- StartFunction(FD, R, Fn, Args, SourceLocation());
- // FIXME: generate body
+ StartFunction(FD, ResultType, Fn, Args, SourceLocation());
+
+ // generate body
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ FPT->isVariadic());
+ llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty);
+ CallArgList CallArgs;
+
+ QualType ArgType = MD->getThisType(getContext());
+ llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
+ if (nv_t || v_t) {
+ // Do the this adjustment.
+ const llvm::Type *OrigTy = Callee->getType();
+ Arg = DynamicTypeAdjust(Arg, nv_t, v_t);
+ if (nv_r || v_r) {
+ Callee = CGM.BuildCovariantThunk(MD, Extern, 0, 0, nv_r, v_r);
+ Callee = Builder.CreateBitCast(Callee, OrigTy);
+ nv_r = v_r = 0;
+ }
+ }
+
+ CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));
+
+ for (FunctionDecl::param_const_iterator i = MD->param_begin(),
+ e = MD->param_end();
+ i != e; ++i) {
+ ParmVarDecl *D = *i;
+ QualType ArgType = D->getType();
+
+ // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
+ Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType, SourceLocation());
+ CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
+ }
+
+ RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ Callee, CallArgs, MD);
+ if (nv_r || v_r) {
+ // Do the return result adjustment.
+ RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+ }
+
+ if (!ResultType->isVoidType())
+ EmitReturnOfRValue(RV, ResultType);
+
FinishFunction();
return Fn;
}
@@ -769,7 +839,6 @@ llvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern,
llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(),
&getModule());
CodeGenFunction(*this).GenerateThunk(Fn, MD, Extern, nv, v);
- // Fn = Builder.CreateBitCast(Fn, Ptr8Ty);
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
return m;
}
@@ -795,7 +864,6 @@ llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
&getModule());
CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r,
v_r);
- // Fn = Builder.CreateBitCast(Fn, Ptr8Ty);
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
return m;
}
@@ -815,7 +883,7 @@ CodeGenFunction::GetVirtualCXXBaseClassOffset(llvm::Value *This,
CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
llvm::Value *VBaseOffsetPtr =
- Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
+ Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
const llvm::Type *PtrDiffTy =
ConvertType(getContext().getPointerDiffType());
@@ -899,7 +967,7 @@ void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
- BaseCopyCtor->getParamDecl(0)->getType()));
+ BaseCopyCtor->getParamDecl(0)->getType()));
QualType ResultType =
BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
@@ -1099,11 +1167,11 @@ CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
FinishFunction();
}
-/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy
-/// constructor, in accordance with section 12.8 (p7 and p8) of C++03
+/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
+/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03
/// The implicitly-defined copy constructor for class X performs a memberwise
-/// copy of its subobjects. The order of copying is the same as the order
-/// of initialization of bases and members in a user-defined constructor
+/// copy of its subobjects. The order of copying is the same as the order of
+/// initialization of bases and members in a user-defined constructor
/// Each subobject is copied in the manner appropriate to its type:
/// if the subobject is of class type, the copy constructor for the class is
/// used;
@@ -1121,7 +1189,7 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args) {
const CXXRecordDecl *ClassDecl = Ctor->getParent();
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
- "SynthesizeCXXCopyConstructor - copy constructor has definition already");
+ "SynthesizeCXXCopyConstructor - copy constructor has definition already");
StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
SourceLocation());
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 78655168e857..06cd05cc75a8 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -441,6 +441,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
RetAttrs |= llvm::Attribute::NoAlias;
}
+ if (CompileOpts.OptimizeSize)
+ FuncAttrs |= llvm::Attribute::OptimizeForSize;
if (CompileOpts.DisableRedZone)
FuncAttrs |= llvm::Attribute::NoRedZone;
if (CompileOpts.NoImplicitFloat)
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1728c67292b7..b1ceb4627712 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompileOptions.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
@@ -316,6 +317,20 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
+
+ // All constant structs and arrays should be global if
+ // their initializer is constant and if the element type is POD.
+ if (CGM.getCompileOpts().MergeAllConstants) {
+ if (Ty.isConstant(getContext())
+ && (Ty->isArrayType() || Ty->isRecordType())
+ && (D.getInit()
+ && D.getInit()->isConstantInitializer(getContext()))
+ && Ty->isPODType()) {
+ EmitStaticBlockVarDecl(D);
+ return;
+ }
+ }
+
// A normal fixed sized variable becomes an alloca in the entry block.
const llvm::Type *LTy = ConvertTypeForMem(Ty);
Align = getContext().getDeclAlignInBytes(&D);
@@ -417,17 +432,18 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
+ bool isVolatile = (getContext().getCanonicalType(D.getType())
+ .isVolatileQualified());
if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(),
- D.getType());
+ EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
- EmitAggExpr(Init, Loc, D.getType().isVolatileQualified());
+ EmitAggExpr(Init, Loc, isVolatile);
}
}
@@ -492,16 +508,25 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
// Handle CXX destruction of variables.
QualType DtorTy(Ty);
if (const ArrayType *Array = DtorTy->getAs<ArrayType>())
- DtorTy = Array->getElementType();
+ DtorTy = getContext().getBaseElementType(Array);
if (const RecordType *RT = DtorTy->getAs<RecordType>())
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!ClassDecl->hasTrivialDestructor()) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- assert(!Ty->getAs<ArrayType>() && "FIXME - destruction of arrays NYI");
-
+
CleanupScope scope(*this);
- EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
+ if (const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(Ty)) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(DeclPtr, BasePtr);
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+ }
+ else
+ EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
}
}
@@ -547,6 +572,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
QualType Ty = D.getType();
+ CanQualType CTy = getContext().getCanonicalType(Ty);
llvm::Value *DeclPtr;
if (!Ty->isConstantSizeType()) {
@@ -563,7 +589,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DeclPtr->setName(Name.c_str());
// Store the initial value into the alloca.
- EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty);
+ EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
} else {
// Otherwise, if this is an aggregate, just use the input pointer.
DeclPtr = Arg;
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
new file mode 100644
index 000000000000..adfd0055f936
--- /dev/null
+++ b/lib/CodeGen/CGException.cpp
@@ -0,0 +1,105 @@
+//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ exception related code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+using namespace clang;
+using namespace CodeGen;
+
+static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
+ // void *__cxa_allocate_exception(size_t thrown_size);
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+ std::vector<const llvm::Type*> Args(1, SizeTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
+}
+
+static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
+ // void __cxa_throw (void *thrown_exception, std::type_info *tinfo,
+ // void (*dest) (void *) );
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(3, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
+}
+
+void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
+ // FIXME: Handle rethrows.
+ if (!E->getSubExpr()) {
+ ErrorUnsupported(E, "rethrow expression");
+ return;
+ }
+
+ QualType ThrowType = E->getSubExpr()->getType();
+ // FIXME: We only handle non-class types for now.
+ if (ThrowType->isRecordType()) {
+ ErrorUnsupported(E, "throw expression");
+ return;
+ }
+
+ // FIXME: Handle cleanup.
+ if (!CleanupEntries.empty()){
+ ErrorUnsupported(E, "throw expression");
+ return;
+ }
+
+ // Now allocate the exception object.
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ uint64_t TypeSize = getContext().getTypeSize(ThrowType) / 8;
+
+ llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
+ llvm::Value *ExceptionPtr =
+ Builder.CreateCall(AllocExceptionFn,
+ llvm::ConstantInt::get(SizeTy, TypeSize),
+ "exception");
+
+ // Store the throw exception in the exception object.
+ if (!hasAggregateLLVMType(ThrowType)) {
+ llvm::Value *Value = EmitScalarExpr(E->getSubExpr());
+ const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
+
+ Builder.CreateStore(Value, Builder.CreateBitCast(ExceptionPtr, ValuePtrTy));
+ } else {
+ // FIXME: Handle complex and aggregate expressions.
+ ErrorUnsupported(E, "throw expression");
+ }
+
+ // Now throw the exception.
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), ThrowType, Out);
+
+ // FIXME: Is it OK to use CreateRuntimeVariable for this?
+ llvm::Constant *TypeInfo =
+ CGM.CreateRuntimeVariable(llvm::Type::getInt8Ty(getLLVMContext()),
+ OutName.c_str());
+ llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy);
+
+ llvm::CallInst *ThrowCall =
+ Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
+ ThrowCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
+}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index bb487f6e3fdf..d9dd70ac9e49 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -84,10 +84,9 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
- if (ShouldDestroyTemporaries) {
- // Keep track of the current cleanup stack depth.
+ // Keep track of the current cleanup stack depth.
+ if (ShouldDestroyTemporaries)
OldNumLiveTemporaries = LiveTemporaries.size();
- }
E = TE->getSubExpr();
}
@@ -148,7 +147,6 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
// Check if need to perform the derived-to-base cast.
if (BaseClassDecl) {
llvm::Value *Derived = Val.getAggregateAddr();
-
llvm::Value *Base =
GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl,
/*NullCheckValue=*/false);
@@ -189,18 +187,21 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
//===----------------------------------------------------------------------===//
RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
- if (Ty->isVoidType()) {
+ if (Ty->isVoidType())
return RValue::get(0);
- } else if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
+
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
const llvm::Type *EltTy = ConvertType(CTy->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return RValue::getComplex(std::make_pair(U, U));
- } else if (hasAggregateLLVMType(Ty)) {
+ }
+
+ if (hasAggregateLLVMType(Ty)) {
const llvm::Type *LTy = llvm::PointerType::getUnqual(ConvertType(Ty));
return RValue::getAggregate(llvm::UndefValue::get(LTy));
- } else {
- return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
}
+
+ return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
}
RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E,
@@ -245,7 +246,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::VAArgExprClass:
return EmitVAArgExprLValue(cast<VAArgExpr>(E));
case Expr::DeclRefExprClass:
- case Expr::QualifiedDeclRefExprClass:
return EmitDeclRefLValue(cast<DeclRefExpr>(E));
case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
case Expr::PredefinedExprClass:
@@ -343,9 +343,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
if (LV.isObjCWeak()) {
// load of a __weak object.
llvm::Value *AddrWeakObj = LV.getAddress();
- llvm::Value *read_weak = CGM.getObjCRuntime().EmitObjCWeakRead(*this,
- AddrWeakObj);
- return RValue::get(read_weak);
+ return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
+ AddrWeakObj));
}
if (LV.isSimple()) {
@@ -522,10 +521,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
if (Dst.isPropertyRef())
return EmitStoreThroughPropertyRefLValue(Src, Dst, Ty);
- if (Dst.isKVCRef())
- return EmitStoreThroughKVCRefLValue(Src, Dst, Ty);
-
- assert(0 && "Unknown LValue type");
+ assert(Dst.isKVCRef() && "Unknown LValue type");
+ return EmitStoreThroughKVCRefLValue(Src, Dst, Ty);
}
if (Dst.isObjCWeak() && !Dst.isNonGC()) {
@@ -551,8 +548,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
BytesBetween);
- }
- else if (Dst.isGlobalObjCRef())
+ } else if (Dst.isGlobalObjCRef())
CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
else
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
@@ -702,13 +698,12 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
// FIXME: since we're shuffling with undef, can we just use the indices
// into that? This could be simpler.
llvm::SmallVector<llvm::Constant*, 4> ExtMask;
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
unsigned i;
for (i = 0; i != NumSrcElts; ++i)
- ExtMask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i));
+ ExtMask.push_back(llvm::ConstantInt::get(Int32Ty, i));
for (; i != NumDstElts; ++i)
- ExtMask.push_back(llvm::UndefValue::get(
- llvm::Type::getInt32Ty(VMContext)));
+ ExtMask.push_back(llvm::UndefValue::get(Int32Ty));
llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0],
ExtMask.size());
llvm::Value *ExtSrcVal =
@@ -717,15 +712,13 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
ExtMaskV, "tmp");
// build identity
llvm::SmallVector<llvm::Constant*, 4> Mask;
- for (unsigned i = 0; i != NumDstElts; ++i) {
- Mask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i));
- }
+ for (unsigned i = 0; i != NumDstElts; ++i)
+ Mask.push_back(llvm::ConstantInt::get(Int32Ty, i));
+
// modify when what gets shuffled in
for (unsigned i = 0; i != NumSrcElts; ++i) {
unsigned Idx = getAccessedFieldNo(i, Elts);
- Mask[Idx] = llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i+NumDstElts);
+ Mask[Idx] = llvm::ConstantInt::get(Int32Ty, i+NumDstElts);
}
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
@@ -736,8 +729,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
} else {
// If the Src is a scalar (not a vector) it must be updating one element.
unsigned InIdx = getAccessedFieldNo(0, Elts);
- llvm::Value *Elt = llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), InIdx);
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+ llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
}
@@ -747,8 +740,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
// setObjCGCLValueClass - sets class of he lvalue for the purpose of
// generating write-barries API. It is currently a global, ivar,
// or neither.
-static
-void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
+static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
+ LValue &LV) {
if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC)
return;
@@ -759,6 +752,7 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
LV.SetObjCArray(LV, E->getType()->isArrayType());
return;
}
+
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
@@ -766,10 +760,15 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
LV.SetGlobalObjCRef(LV, true);
}
LV.SetObjCArray(LV, E->getType()->isArrayType());
+ return;
}
- else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E))
+
+ if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
+ return;
+ }
+
+ if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
if (LV.isObjCIvar()) {
// If cast is to a structure pointer, follow gcc's behavior and make it
@@ -779,13 +778,20 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
if (ExpTy->isRecordType())
LV.SetObjCIvar(LV, false);
- }
+ }
+ return;
}
- else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E))
+ if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E))
+ return;
+ }
+
+ if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
+ return;
+ }
+
+ if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
if (LV.isObjCIvar() && !LV.isObjCArray())
// Using array syntax to assigning to what an ivar points to is not
@@ -795,12 +801,15 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
// Using array syntax to assigning to what global points to is not
// same as assigning to the global itself. {id *G;} G[i] = 0;
LV.SetGlobalObjCRef(LV, false);
+ return;
}
- else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+
+ if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
// We don't know if member is an 'ivar', but this flag is looked at
// only in the context of LV.isObjCIvar().
LV.SetObjCArray(LV, E->getType()->isArrayType());
+ return;
}
}
@@ -839,14 +848,18 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
LValue::SetObjCNonGC(LV, NonGCable);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
- } else if (VD && VD->isFileVarDecl()) {
+ }
+
+ if (VD && VD->isFileVarDecl()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
setObjCGCLValueClass(getContext(), E, LV);
return LV;
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
+ }
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
llvm::Value* V = CGM.GetAddrOfFunction(FD);
if (!FD->hasPrototype()) {
if (const FunctionProtoType *Proto =
@@ -861,15 +874,19 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
}
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- } else if (const ImplicitParamDecl *IPD =
- dyn_cast<ImplicitParamDecl>(E->getDecl())) {
+ }
+
+ if (const ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(E->getDecl())){
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- } else if (const QualifiedDeclRefExpr *QDRExpr =
- dyn_cast<QualifiedDeclRefExpr>(E)) {
- return EmitPointerToDataMemberLValue(QDRExpr);
}
+
+ if (E->getQualifier()) {
+ // FIXME: the qualifier check does not seem sufficient here
+ return EmitPointerToDataMemberLValue(E);
+ }
+
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
//ensure that this point is never reached.
@@ -888,25 +905,24 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType());
switch (E->getOpcode()) {
default: assert(0 && "Unknown unary operator lvalue!");
- case UnaryOperator::Deref:
- {
- QualType T = E->getSubExpr()->getType()->getPointeeType();
- assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
-
- Qualifiers Quals = MakeQualifiers(T);
- Quals.setAddressSpace(ExprTy.getAddressSpace());
-
- LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
- // We should not generate __weak write barrier on indirect reference
- // of a pointer to object; as in void foo (__weak id *param); *param = 0;
- // But, we continue to generate __strong write barrier on indirect write
- // into a pointer to object.
- if (getContext().getLangOptions().ObjC1 &&
- getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
- LV.isObjCWeak())
- LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
- return LV;
- }
+ case UnaryOperator::Deref: {
+ QualType T = E->getSubExpr()->getType()->getPointeeType();
+ assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
+
+ Qualifiers Quals = MakeQualifiers(T);
+ Quals.setAddressSpace(ExprTy.getAddressSpace());
+
+ LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
+ // We should not generate __weak write barrier on indirect reference
+ // of a pointer to object; as in void foo (__weak id *param); *param = 0;
+ // But, we continue to generate __strong write barrier on indirect write
+ // into a pointer to object.
+ if (getContext().getLangOptions().ObjC1 &&
+ getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
+ LV.isObjCWeak())
+ LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+ return LV;
+ }
case UnaryOperator::Real:
case UnaryOperator::Imag:
LValue LV = EmitLValue(E->getSubExpr());
@@ -932,8 +948,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
std::string GlobalVarName;
switch (Type) {
- default:
- assert(0 && "Invalid type");
+ default: assert(0 && "Invalid type");
case PredefinedExpr::Func:
GlobalVarName = "__func__.";
break;
@@ -1089,12 +1104,12 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
llvm::Constant *BaseElts = Base.getExtVectorElts();
llvm::SmallVector<llvm::Constant *, 4> CElts;
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
if (isa<llvm::ConstantAggregateZero>(BaseElts))
- CElts.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), 0));
+ CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0));
else
- CElts.push_back(BaseElts->getOperand(Indices[i]));
+ CElts.push_back(cast<llvm::Constant>(BaseElts->getOperand(Indices[i])));
}
llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size());
return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
@@ -1211,13 +1226,12 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
const Expr* InitExpr = E->getInitializer();
LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
- if (E->getType()->isComplexType()) {
+ if (E->getType()->isComplexType())
EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
- } else if (hasAggregateLLVMType(E->getType())) {
+ else if (hasAggregateLLVMType(E->getType()))
EmitAnyExpr(InitExpr, DeclPtr, false);
- } else {
+ else
EmitStoreThroughLValue(EmitAnyExpr(InitExpr), Result, E->getType());
- }
return Result;
}
@@ -1238,9 +1252,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
if (!LHS.isSimple())
return EmitUnsupportedLValue(E, "conditional operator");
- llvm::Value *Temp = CreateTempAlloca(LHS.getAddress()->getType(),
- "condtmp");
-
+ llvm::Value *Temp = CreateTempAlloca(LHS.getAddress()->getType(),"condtmp");
Builder.CreateStore(LHS.getAddress(), Temp);
EmitBranch(ContBlock);
@@ -1379,7 +1391,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitLValue(E->getRHS());
}
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BinaryOperator::PtrMemD ||
+ E->getOpcode() == BinaryOperator::PtrMemI)
return EmitPointerToDataMemberBinaryExpr(E);
// Can only get l-value for binary operator expressions which are a
@@ -1406,15 +1419,14 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
RValue RV = EmitCallExpr(E);
- if (RV.isScalar()) {
- assert(E->getCallReturnType()->isReferenceType() &&
- "Can't have a scalar return unless the return type is a "
- "reference type!");
-
- return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
- }
+ if (!RV.isScalar())
+ return LValue::MakeAddr(RV.getAggregateAddr(),MakeQualifiers(E->getType()));
+
+ assert(E->getCallReturnType()->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
- return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
+ return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
@@ -1439,9 +1451,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
LValue
CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
-
PushCXXTemporary(E->getTemporary(), LV.getAddress());
-
return LV;
}
@@ -1497,21 +1507,18 @@ CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) {
return LValue::MakePropertyRef(E, E->getType().getCVRQualifiers());
}
-LValue
-CodeGenFunction::EmitObjCKVCRefLValue(
+LValue CodeGenFunction::EmitObjCKVCRefLValue(
const ObjCImplicitSetterGetterRefExpr *E) {
// This is a special l-value that just issues sends when we load or store
// through it.
return LValue::MakeKVCRef(E, E->getType().getCVRQualifiers());
}
-LValue
-CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) {
+LValue CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) {
return EmitUnsupportedLValue(E, "use of super");
}
LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
-
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
// FIXME: can this be volatile?
@@ -1519,8 +1526,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
-LValue CodeGenFunction::EmitPointerToDataMemberLValue(
- const QualifiedDeclRefExpr *E) {
+LValue CodeGenFunction::EmitPointerToDataMemberLValue(const DeclRefExpr *E) {
const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
QualType NNSpecTy =
@@ -1530,12 +1536,9 @@ LValue CodeGenFunction::EmitPointerToDataMemberLValue(
llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
/*isUnion*/false, /*Qualifiers*/0);
- const llvm::Type* ResultType = ConvertType(
- getContext().getPointerDiffType());
- V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,
- "datamember");
- LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- return LV;
+ const llvm::Type *ResultType = ConvertType(getContext().getPointerDiffType());
+ V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType, "datamember");
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
}
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
@@ -1566,9 +1569,11 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
Callee, Args, TargetDecl);
}
-LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
- const BinaryOperator *E) {
+LValue CodeGenFunction::
+EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
+ if (E->getOpcode() == BinaryOperator::PtrMemI)
+ BaseV = Builder.CreateLoad(BaseV, "indir.ptr");
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
BaseV = Builder.CreateBitCast(BaseV, i8Ty);
LValue RHSLV = EmitLValue(E->getRHS());
@@ -1577,13 +1582,12 @@ LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
+
QualType Ty = E->getRHS()->getType();
- const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>();
- Ty = MemPtrType->getPointeeType();
- const llvm::Type* PType =
- ConvertType(getContext().getPointerType(Ty));
+ Ty = Ty->getAs<MemberPointerType>()->getPointeeType();
+
+ const llvm::Type *PType = ConvertType(getContext().getPointerType(Ty));
AddV = Builder.CreateBitCast(AddV, PType);
- LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty));
- return LV;
+ return LValue::MakeAddr(AddV, MakeQualifiers(Ty));
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index f47b6ab3c8cc..901f867a5913 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -297,7 +297,7 @@ void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
assert(MPT->getPointeeType()->isFunctionProtoType() &&
"Unexpected member pointer type!");
- const QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr());
+ const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
const llvm::Type *PtrDiffTy =
@@ -329,7 +329,8 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
}
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BinaryOperator::PtrMemD ||
+ E->getOpcode() == BinaryOperator::PtrMemI)
VisitPointerToDataMemberBinaryOperator(E);
else
CGF.ErrorUnsupported(E, "aggregate binary expression");
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index fc3748c8e3c8..9145d92128a1 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -228,7 +228,7 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
- llvm::Constant *C = llvm::Constant::getNullValue(Ty);
+ llvm::Constant *C = llvm::UndefValue::get(Ty);
Elements.push_back(C);
assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
@@ -266,7 +266,7 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
- llvm::Constant *Padding = llvm::Constant::getNullValue(Ty);
+ llvm::Constant *Padding = llvm::UndefValue::get(Ty);
PackedElements.push_back(Padding);
ElementOffsetInBytes += getSizeInBytes(Padding);
}
@@ -434,7 +434,7 @@ public:
E->getType()->getAs<MemberPointerType>()) {
QualType T = MPT->getPointeeType();
if (T->isFunctionProtoType()) {
- QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr());
+ DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
return EmitMemberFunctionPointer(cast<CXXMethodDecl>(DRE->getDecl()));
}
@@ -496,7 +496,7 @@ public:
if (NumPadBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumPadBytes);
- Elts.push_back(llvm::Constant::getNullValue(Ty));
+ Elts.push_back(llvm::UndefValue::get(Ty));
Types.push_back(Ty);
}
@@ -739,8 +739,7 @@ public:
E->getType().getAddressSpace());
return C;
}
- case Expr::DeclRefExprClass:
- case Expr::QualifiedDeclRefExprClass: {
+ case Expr::DeclRefExprClass: {
NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
return CGM.GetAddrOfFunction(FD);
@@ -777,11 +776,17 @@ public:
}
case Expr::AddrLabelExprClass: {
assert(CGF && "Invalid address of label expression outside function.");
+#ifndef USEINDIRECTBRANCH
unsigned id =
CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
llvm::Constant *C =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), id);
return llvm::ConstantExpr::getIntToPtr(C, ConvertType(E->getType()));
+#else
+ llvm::Constant *Ptr =
+ CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
+ return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+#endif
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 69604f9aaaee..96b58d8995ae 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -135,11 +135,16 @@ public:
}
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
+#ifndef USEINDIRECTBRANCH
llvm::Value *V =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()),
CGF.GetIDForAddrOfLabel(E->getLabel()));
return Builder.CreateIntToPtr(V, ConvertType(E->getType()));
+#else
+ llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
+ return Builder.CreateBitCast(V, ConvertType(E->getType()));
+#endif
}
// l-values.
@@ -272,7 +277,12 @@ public:
Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
return llvm::Constant::getNullValue(ConvertType(E->getType()));
}
-
+
+ Value *VisitCXXThrowExpr(const CXXThrowExpr *E) {
+ CGF.EmitCXXThrowExpr(E);
+ return 0;
+ }
+
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
if (CGF.getContext().getLangOptions().OverflowChecking
@@ -678,14 +688,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
// If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
// input is the same width as the vector being constructed, generate an
// optimized shuffle of the swizzle input into the result.
+ unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
if (isa<ExtVectorElementExpr>(IE)) {
llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
Value *SVOp = SVI->getOperand(0);
const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
if (OpTy->getNumElements() == ResElts) {
- unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
-
for (unsigned j = 0; j != CurIdx; ++j) {
// If the current vector initializer is a shuffle with undef, merge
// this shuffle directly into it.
@@ -717,13 +726,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
Args.push_back(llvm::UndefValue::get(I32Ty));
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
- Mask, "vecext");
+ Mask, "vext");
Args.clear();
for (unsigned j = 0; j != CurIdx; ++j)
Args.push_back(llvm::ConstantInt::get(I32Ty, j));
for (unsigned j = 0; j != InitElts; ++j)
- Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts));
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j+Offset));
for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
Args.push_back(llvm::UndefValue::get(I32Ty));
}
@@ -1639,9 +1648,10 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
/// expression is cheap enough and side-effect-free enough to evaluate
/// unconditionally instead of conditionally. This is used to convert control
/// flow into selects in some cases.
-static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
+static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+ CodeGenFunction &CGF) {
if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
- return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr());
+ return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF);
// TODO: Allow anything we can constant fold to an integer or fp constant.
if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||
@@ -1652,7 +1662,9 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
// X and Y are local variables.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
- if (VD->hasLocalStorage() && !VD->getType().isVolatileQualified())
+ if (VD->hasLocalStorage() && !(CGF.getContext()
+ .getCanonicalType(VD->getType())
+ .isVolatileQualified()))
return true;
return false;
@@ -1681,8 +1693,9 @@ VisitConditionalOperator(const ConditionalOperator *E) {
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
- if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS()) &&
- isCheapEnoughToEvaluateUnconditionally(E->getRHS())) {
+ if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS(),
+ CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(E->getRHS(), CGF)) {
llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
llvm::Value *LHS = Visit(E->getLHS());
llvm::Value *RHS = Visit(E->getRHS());
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index cadba328bf12..2fe3f5b1b443 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -280,17 +280,29 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args),
SetPropertyFn, Args);
} else {
+ // FIXME: Find a clean way to avoid AST node creation.
SourceLocation Loc = PD->getLocation();
ValueDecl *Self = OMD->getSelfDecl();
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
DeclRefExpr Base(Self, Self->getType(), Loc);
ParmVarDecl *ArgDecl = *OMD->param_begin();
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
- ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
- true, true);
- BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
- Ivar->getType(), Loc);
- EmitStmt(&Assign);
+ ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
+
+ // The property type can differ from the ivar type in some situations with
+ // Objective-C pointer types, we can always bit cast the RHS in these cases.
+ if (getContext().getCanonicalType(Ivar->getType()) !=
+ getContext().getCanonicalType(ArgDecl->getType())) {
+ ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
+ false);
+ BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
+ Ivar->getType(), Loc);
+ EmitStmt(&Assign);
+ } else {
+ BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
+ Ivar->getType(), Loc);
+ EmitStmt(&Assign);
+ }
}
FinishFunction();
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.h b/lib/CodeGen/CGRecordLayoutBuilder.h
index d1a13aa29711..4ebf4e88decb 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.h
+++ b/lib/CodeGen/CGRecordLayoutBuilder.h
@@ -15,7 +15,7 @@
#define CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <vector>
namespace llvm {
diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp
index 7bc774fce75b..7af15f0a8ca4 100644
--- a/lib/CodeGen/CGRtti.cpp
+++ b/lib/CodeGen/CGRtti.cpp
@@ -16,32 +16,31 @@ using namespace clang;
using namespace CodeGen;
llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
- llvm::Type *Ptr8Ty;
- Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
- llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
if (!getContext().getLangOptions().Rtti)
- return Rtti;
+ return llvm::Constant::getNullValue(Int8PtrTy);
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- mangleCXXRtti(getMangleContext(), RD, Out);
+ mangleCXXRtti(getMangleContext(), Context.getTagDeclType(RD), Out);
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::WeakAnyLinkage;
std::vector<llvm::Constant *> info;
// assert(0 && "FIXME: implement rtti descriptor");
// FIXME: descriptor
- info.push_back(llvm::Constant::getNullValue(Ptr8Ty));
+ info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
// assert(0 && "FIXME: implement rtti ts");
// FIXME: TS
- info.push_back(llvm::Constant::getNullValue(Ptr8Ty));
+ info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
llvm::Constant *C;
- llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size());
+ llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
C = llvm::ConstantArray::get(type, info);
- Rtti = new llvm::GlobalVariable(getModule(), type, true, linktype, C,
- Out.str());
- Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty);
+ llvm::Constant *Rtti =
+ new llvm::GlobalVariable(getModule(), type, true, linktype, C,
+ Out.str());
+ Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
return Rtti;
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index f58b57926787..9126c2c99cdf 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -287,8 +287,13 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
// Emit initial switch which will be patched up later by
// EmitIndirectSwitches(). We need a default dest, so we use the
// current BB, but this is overwritten.
+#ifndef USEINDIRECTBRANCH
llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
llvm::Type::getInt32Ty(VMContext),
+#else
+ llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
+ llvm::Type::getInt8PtrTy(VMContext),
+#endif
"addr");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 2a06f51f6685..fa77471bce0e 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -47,7 +47,7 @@ public:
bool isVolatileQualified() const { return Volatile; }
- /// getScalar() - Return the Value* of this scalar value.
+ /// getScalarVal() - Return the Value* of this scalar value.
llvm::Value *getScalarVal() const {
assert(isScalar() && "Not a scalar!");
return V1;
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 9df0e1abd547..e2e11478de26 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -43,6 +43,9 @@ private:
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
+
+ typedef llvm::DenseMap<const CXXMethodDecl *, int> Pures_t;
+ Pures_t Pures;
typedef std::pair<Index_t, Index_t> CallOffset;
typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t;
Thunks_t Thunks;
@@ -58,6 +61,7 @@ private:
Index_t extra;
int CurrentVBaseOffset;
typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
+ llvm::Constant *cxa_pure;
public:
VtableBuilder(std::vector<llvm::Constant *> &meth,
const CXXRecordDecl *c,
@@ -68,6 +72,13 @@ public:
LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)),
CurrentVBaseOffset(0) {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+
+ // Calculate pointer for ___cxa_pure_virtual.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual"));
}
llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
@@ -84,8 +95,10 @@ public:
return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
}
- void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets,
- const CXXRecordDecl *RD, uint64_t Offset,
+#define D1(x)
+//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
+
+ void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
bool updateVBIndex, Index_t current_vbindex) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
@@ -94,22 +107,24 @@ public:
Index_t next_vbindex = current_vbindex;
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
- int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
- llvm::Constant *m = wrap(BaseOffset);
- m = wrap((0?700:0) + BaseOffset);
if (updateVBIndex) {
- next_vbindex = (ssize_t)(-(offsets.size()*LLVMPointerWidth/8)
+ next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
- 3*LLVMPointerWidth/8);
VBIndex[Base] = next_vbindex;
}
- offsets.push_back(m);
+ int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
+ VCalls.push_back((0?700:0) + BaseOffset);
+ D1(printf(" vbase for %s at %d delta %d most derived %s\n",
+ Base->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)BaseOffset,
+ Class->getNameAsCString()));
}
// We also record offsets for non-virtual bases to closest enclosing
// virtual base. We do this so that we don't have to search
// for the nearst virtual base class when generating thunks.
if (updateVBIndex && VBIndex.count(Base) == 0)
VBIndex[Base] = next_vbindex;
- GenerateVBaseOffsets(offsets, Base, Offset, updateVBIndex, next_vbindex);
+ GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
}
}
@@ -144,8 +159,8 @@ public:
/// getNVOffset - Returns the non-virtual offset for the given (B) base of the
/// derived class D.
Index_t getNVOffset(QualType qB, QualType qD) {
- qD = qD->getAs<PointerType>()->getPointeeType();
- qB = qB->getAs<PointerType>()->getPointeeType();
+ qD = qD->getPointeeType();
+ qB = qB->getPointeeType();
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
int64_t o = getNVOffset_1(D, B);
@@ -159,8 +174,8 @@ public:
/// getVbaseOffset - Returns the index into the vtable for the virtual base
/// offset for the given (B) virtual base of the derived class D.
Index_t getVbaseOffset(QualType qB, QualType qD) {
- qD = qD->getAs<PointerType>()->getPointeeType();
- qB = qB->getAs<PointerType>()->getPointeeType();
+ qD = qD->getPointeeType();
+ qB = qB->getPointeeType();
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
if (D != Class)
@@ -177,6 +192,7 @@ public:
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
bool MorallyVirtual, Index_t OverrideOffset,
Index_t Offset) {
+ const bool isPure = MD->isPure();
typedef CXXMethodDecl::method_iterator meth_iter;
// FIXME: Should OverrideOffset's be Offset?
@@ -215,7 +231,9 @@ public:
}
Index[MD] = i;
submethods[i] = m;
-
+ if (isPure)
+ Pures[MD] = 1;
+ Pures.erase(OMD);
Thunks.erase(OMD);
if (MorallyVirtual) {
Index_t &idx = VCall[OMD];
@@ -223,9 +241,17 @@ public:
VCallOffset[MD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
+ D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
+ MD->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)VCallOffset[MD],
+ Class->getNameAsCString()));
} else {
VCallOffset[MD] = VCallOffset[OMD];
VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+ D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
+ MD->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)VCallOffset[MD],
+ Class->getNameAsCString()));
}
VCall[MD] = idx;
CallOffset ThisOffset;
@@ -237,7 +263,7 @@ public:
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
- else
+ else if (!isPure)
Thunks[MD] = ThisOffset;
return true;
}
@@ -252,7 +278,7 @@ public:
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
- else
+ else if (!isPure)
Thunks[MD] = ThisOffset;
}
return true;
@@ -266,6 +292,7 @@ public:
for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end();
i != e; ++i) {
const CXXMethodDecl *MD = i->first;
+ assert(!MD->isPure() && "Trying to thunk a pure");
Index_t idx = Index[MD];
Index_t nv_O = i->second.first;
Index_t v_O = i->second.second;
@@ -276,6 +303,8 @@ public:
e = CovariantThunks.end();
i != e; ++i) {
const CXXMethodDecl *MD = i->first;
+ if (MD->isPure())
+ continue;
Index_t idx = Index[MD];
Index_t nv_t = i->second.first.first.first;
Index_t v_t = i->second.first.first.second;
@@ -285,6 +314,25 @@ public:
v_r);
}
CovariantThunks.clear();
+ for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
+ i != e; ++i) {
+ const CXXMethodDecl *MD = i->first;
+ Index_t idx = Index[MD];
+ submethods[idx] = cxa_pure;
+ }
+ Pures.clear();
+ }
+
+ llvm::Constant *WrapAddrOf(const CXXMethodDecl *MD) {
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
+ return wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ FPT->isVariadic());
+
+ return wrap(CGM.GetAddrOfFunction(MD, Ty));
}
void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
@@ -298,37 +346,16 @@ public:
continue;
const CXXMethodDecl *MD = *mi;
- llvm::Constant *m = 0;
- if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
- else {
- const FunctionProtoType *FPT =
- MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
-
- m = wrap(CGM.GetAddrOfFunction(MD, Ty));
- }
-
+ llvm::Constant *m = WrapAddrOf(MD);
OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
}
}
}
- void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) {
- llvm::Constant *m = 0;
- if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
- else {
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
-
- m = wrap(CGM.GetAddrOfFunction(MD, Ty));
- }
-
+ void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset,
+ bool ForVirtualBase) {
+ llvm::Constant *m = WrapAddrOf(MD);
+
// If we can find a previously allocated slot for this, reuse it.
if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
return;
@@ -336,6 +363,9 @@ public:
// else allocate a new slot.
Index[MD] = submethods.size();
submethods.push_back(m);
+ D1(printf(" vfn for %s at %d\n", MD->getNameAsCString(), (int)Index[MD]));
+ if (MD->isPure())
+ Pures[MD] = 1;
if (MorallyVirtual) {
VCallOffset[MD] = Offset/8;
Index_t &idx = VCall[MD];
@@ -343,16 +373,19 @@ public:
if (idx == 0) {
idx = VCalls.size()+1;
VCalls.push_back(0);
+ D1(printf(" vcall for %s at %d with delta %d\n",
+ MD->getNameAsCString(), (int)-VCalls.size()-3,
+ (int)VCallOffset[MD]));
}
}
}
void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
- Index_t Offset) {
+ Index_t Offset, bool RDisVirtualBase) {
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi)
if (mi->isVirtual())
- AddMethod(*mi, MorallyVirtual, Offset);
+ AddMethod(*mi, MorallyVirtual, Offset, RDisVirtualBase);
}
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
@@ -381,6 +414,7 @@ public:
void insertVCalls(int InsertionPoint) {
llvm::Constant *e = 0;
+ D1(printf("============= combining vbase/vcall\n"));
D(VCalls.insert(VCalls.begin(), 673));
D(VCalls.push_back(672));
methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
@@ -392,11 +426,10 @@ public:
VCalls.clear();
}
- Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets,
- const ASTRecordLayout &Layout,
- const CXXRecordDecl *PrimaryBase,
- bool PrimaryBaseWasVirtual, bool MorallyVirtual,
- int64_t Offset, bool ForVirtualBase, Path_t *Path) {
+ Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
+ const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
+ bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
+ Path_t *Path) {
bool alloc = false;
if (Path == 0) {
alloc = true;
@@ -405,16 +438,6 @@ public:
StartNewTable();
extra = 0;
- // FIXME: Cleanup.
- if (!ForVirtualBase) {
- D(methods.push_back(wrap(666)));
- // then virtual base offsets...
- for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
- e = offsets.rend(); i != e; ++i)
- methods.push_back(*i);
- D(methods.push_back(wrap(667)));
- }
-
bool DeferVCalls = MorallyVirtual || ForVirtualBase;
int VCallInsertionPoint = methods.size();
if (!DeferVCalls) {
@@ -423,20 +446,12 @@ public:
// FIXME: just for extra, or for all uses of VCalls.size post this?
extra = -VCalls.size();
- if (ForVirtualBase) {
- D(methods.push_back(wrap(668)));
- // then virtual base offsets...
- for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
- e = offsets.rend(); i != e; ++i)
- methods.push_back(*i);
- D(methods.push_back(wrap(669)));
- }
-
methods.push_back(wrap(-(Offset/8)));
methods.push_back(rtti);
Index_t AddressPoint = methods.size();
InstallThunks();
+ D1(printf("============= combining methods\n"));
methods.insert(methods.end(), submethods.begin(), submethods.end());
submethods.clear();
@@ -445,10 +460,8 @@ public:
MorallyVirtual, Offset, Path);
if (ForVirtualBase) {
- D(methods.push_back(wrap(670)));
insertVCalls(VCallInsertionPoint);
AddressPoint += VCalls.size();
- D(methods.push_back(wrap(671)));
}
if (alloc) {
@@ -457,7 +470,36 @@ public:
return AddressPoint;
}
- void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) {
+ void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+ bool updateVBIndex, Index_t current_vbindex,
+ bool RDisVirtualBase) {
+ if (!RD->isDynamicClass())
+ return;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
+
+ // vtables are composed from the chain of primaries.
+ if (PrimaryBase) {
+ D1(printf(" doing primaries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ if (!PrimaryBaseWasVirtual)
+ Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
+ }
+
+ D1(printf(" doing vcall entries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ // And add the virtuals for the class to the primary vtable.
+ AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase);
+ }
+
+ void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+ bool updateVBIndex, Index_t current_vbindex,
+ bool RDisVirtualBase, bool bottom=false) {
if (!RD->isDynamicClass())
return;
@@ -469,11 +511,22 @@ public:
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
- Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset);
+
+ D1(printf(" doing primaries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
}
- // And add the virtuals for the class to the primary vtable.
- AddMethods(RD, MorallyVirtual, Offset);
+ D1(printf(" doing vbase entries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+ GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
+
+ if (RDisVirtualBase || bottom) {
+ Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
+ RDisVirtualBase);
+ }
}
int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
@@ -487,27 +540,21 @@ public:
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
- std::vector<llvm::Constant *> offsets;
extra = 0;
- GenerateVBaseOffsets(offsets, RD, Offset, !ForVirtualBase, 0);
- if (ForVirtualBase)
- extra = offsets.size();
+ D1(printf("building entries for base %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
- // vtables are composed from the chain of primaries.
- if (PrimaryBase) {
- if (PrimaryBaseWasVirtual)
- IndirectPrimary.insert(PrimaryBase);
- Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset);
- }
+ if (ForVirtualBase)
+ extra = VCalls.size();
- // And add the virtuals for the class to the primary vtable.
- AddMethods(RD, MorallyVirtual, Offset);
+ VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
+ true);
if (Path)
OverrideMethods(Path, MorallyVirtual, Offset);
- return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset, ForVirtualBase, Path);
+ return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
+ Offset, ForVirtualBase, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
@@ -532,6 +579,8 @@ public:
VCall.clear();
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
CurrentVBaseOffset = BaseOffset;
+ D1(printf("vtable %s virtual base %s\n",
+ Class->getNameAsCString(), Base->getNameAsCString()));
GenerateVtableForBase(Base, true, BaseOffset, true, Path);
}
int64_t BaseOffset = Offset;
@@ -567,6 +616,7 @@ int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) {
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -591,6 +641,7 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -614,13 +665,14 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
mangleCXXVtable(CGM.getMangleContext(), RD, Out);
llvm::GlobalVariable::LinkageTypes linktype;
- linktype = llvm::GlobalValue::WeakAnyLinkage;
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
std::vector<llvm::Constant *> methods;
llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
int64_t AddressPoint;
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
// First comes the vtables for all the non-virtual bases...
AddressPoint = b.GenerateVtableForBase(RD);
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 2f46313c9c20..10884a7560f5 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangCodeGen
CGCall.cpp
CGDebugInfo.cpp
CGDecl.cpp
+ CGException.cpp
CGExpr.cpp
CGExprAgg.cpp
CGExprComplex.cpp
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index ba93e5d0ebc8..88beadf33140 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -27,7 +27,11 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
: BlockFunction(cgm, *this, Builder), CGM(cgm),
Target(CGM.getContext().Target),
Builder(cgm.getModule().getContext()),
+#ifndef USEINDIRECTBRANCH
DebugInfo(0), IndirectGotoSwitch(0),
+#else
+ DebugInfo(0), IndirectBranch(0),
+#endif
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
CXXThisDecl(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
@@ -130,10 +134,33 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitFunctionEpilog(*CurFnInfo, ReturnValue);
+#ifdef USEINDIRECTBRANCH
+ // If someone did an indirect goto, emit the indirect goto block at the end of
+ // the function.
+ if (IndirectBranch) {
+ EmitBlock(IndirectBranch->getParent());
+ Builder.ClearInsertionPoint();
+ }
+
+
+#endif
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = 0;
Ptr->eraseFromParent();
+#ifdef USEINDIRECTBRANCH
+
+ // If someone took the address of a label but never did an indirect goto, we
+ // made a zero entry PHI node, which is illegal, zap it now.
+ if (IndirectBranch) {
+ llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
+ if (PN->getNumIncomingValues() == 0) {
+ PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType()));
+ PN->eraseFromParent();
+ }
+ }
+
+#endif
}
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
@@ -466,13 +493,26 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
TypeInfo.second/8));
}
+#ifndef USEINDIRECTBRANCH
unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
// Use LabelIDs.size()+1 as the new ID if one hasn't been assigned.
unsigned &Entry = LabelIDs[L];
if (Entry) return Entry;
+#else
+
+llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
+ // Make sure that there is a block for the indirect goto.
+ if (IndirectBranch == 0)
+ GetIndirectGotoBlock();
+#endif
+#ifndef USEINDIRECTBRANCH
Entry = LabelIDs.size();
+#else
+ llvm::BasicBlock *BB = getBasicBlockForLabel(L);
+#endif
+#ifndef USEINDIRECTBRANCH
// If this is the first "address taken" of a label and the indirect goto has
// already been seen, add this to it.
if (IndirectGotoSwitch) {
@@ -488,18 +528,42 @@ unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
}
return Entry;
+#else
+ // Make sure the indirect branch includes all of the address-taken blocks.
+ IndirectBranch->addDestination(BB);
+ return llvm::BlockAddress::get(CurFn, BB);
+#endif
}
llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
+#ifndef USEINDIRECTBRANCH
// If we already made the switch stmt for indirect goto, return its block.
if (IndirectGotoSwitch) return IndirectGotoSwitch->getParent();
+#else
+ // If we already made the indirect branch for indirect goto, return its block.
+ if (IndirectBranch) return IndirectBranch->getParent();
+#endif
+#ifndef USEINDIRECTBRANCH
EmitBlock(createBasicBlock("indirectgoto"));
+#else
+ CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
+#endif
+#ifndef USEINDIRECTBRANCH
+ const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+#else
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+#endif
+
// Create the PHI node that indirect gotos will add entries to.
- llvm::Value *DestVal =
- Builder.CreatePHI(llvm::Type::getInt32Ty(VMContext), "indirect.goto.dest");
+#ifndef USEINDIRECTBRANCH
+ llvm::Value *DestVal = Builder.CreatePHI(Int32Ty, "indirect.goto.dest");
+#else
+ llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest");
+#endif
+#ifndef USEINDIRECTBRANCH
// Create the switch instruction. For now, set the insert block to this block
// which will be fixed as labels are added.
IndirectGotoSwitch = Builder.CreateSwitch(DestVal, Builder.GetInsertBlock());
@@ -524,8 +588,6 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
IndirectGotoSwitch->setSuccessor(0,
getBasicBlockForLabel(AddrTakenLabelsByID[0]));
- const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
-
// FIXME: The iteration order of this is nondeterminstic!
for (unsigned i = 1, e = AddrTakenLabelsByID.size(); i != e; ++i)
IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, i+1),
@@ -541,6 +603,11 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
}
return IndirectGotoSwitch->getParent();
+#else
+ // Create the indirect branch instruction.
+ IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
+ return IndirectBranch->getParent();
+#endif
}
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 639e683f0369..9bb219642ab4 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -183,13 +183,22 @@ public:
void PopConditionalTempDestruction();
private:
- CGDebugInfo* DebugInfo;
+ CGDebugInfo *DebugInfo;
+#ifndef USEINDIRECTBRANCH
/// LabelIDs - Track arbitrary ids assigned to labels for use in implementing
/// the GCC address-of-label extension and indirect goto. IDs are assigned to
/// labels inside getIDForAddrOfLabel().
std::map<const LabelStmt*, unsigned> LabelIDs;
+#else
+ /// IndirectBranch - The first time an indirect goto is seen we create a
+ /// block with an indirect branch. Every time we see the address of a label
+ /// taken, we add the label to the indirect goto. Every subsequent indirect
+ /// goto is codegen'd as a jump to the IndirectBranch's basic block.
+ llvm::IndirectBrInst *IndirectBranch;
+#endif
+#ifndef USEINDIRECTBRANCH
/// IndirectGotoSwitch - The first time an indirect goto is seen we create a
/// block with the switch for the indirect gotos. Every time we see the
/// address of a label taken, we add the label to the indirect goto. Every
@@ -197,6 +206,7 @@ private:
/// IndirectGotoSwitch's basic block.
llvm::SwitchInst *IndirectGotoSwitch;
+#endif
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
@@ -377,6 +387,11 @@ public:
/// GenerateVtable - Generate the vtable for the given type.
llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
+ /// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
+ /// object pointer to alter the dynamic type of the pointer. Used by
+ /// GenerateCovariantThunk for building thunks.
+ llvm::Value *DynamicTypeAdjust(llvm::Value *V, int64_t nv, int64_t v);
+
/// GenerateThunk - Generate a thunk for the given method
llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
bool Extern, int64_t nv, int64_t v);
@@ -502,7 +517,7 @@ public:
//===--------------------------------------------------------------------===//
Qualifiers MakeQualifiers(QualType T) {
- Qualifiers Quals = T.getQualifiers();
+ Qualifiers Quals = getContext().getCanonicalType(T).getQualifiers();
Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
return Quals;
}
@@ -558,7 +573,11 @@ public:
/// the input field number being accessed.
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
+#ifndef USEINDIRECTBRANCH
unsigned GetIDForAddrOfLabel(const LabelStmt *L);
+#else
+ llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
+#endif
llvm::BasicBlock *GetIndirectGotoBlock();
/// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
@@ -819,7 +838,7 @@ public:
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
- LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E);
+ LValue EmitPointerToDataMemberLValue(const DeclRefExpr *E);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
@@ -1000,6 +1019,8 @@ public:
bool IsAggLocVolatile = false,
bool IsInitializer = false);
+ void EmitCXXThrowExpr(const CXXThrowExpr *E);
+
//===--------------------------------------------------------------------===//
// Internal Helpers
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index ea84829b78a5..db609f62453c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -253,6 +253,10 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
if (FD->isInAnonymousNamespace())
return CodeGenModule::GVA_Internal;
+ // "static" functions get internal linkage.
+ if (FD->getStorageClass() == FunctionDecl::Static && !isa<CXXMethodDecl>(FD))
+ return CodeGenModule::GVA_Internal;
+
// The kind of external linkage this function will have, if it is not
// inline or static.
CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
@@ -260,19 +264,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
External = CodeGenModule::GVA_TemplateInstantiation;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- // C++ member functions defined inside the class are always inline.
- if (MD->isInline() || !MD->isOutOfLine())
- return CodeGenModule::GVA_CXXInline;
-
- return External;
- }
-
- // "static" functions get internal linkage.
- if (FD->getStorageClass() == FunctionDecl::Static)
- return CodeGenModule::GVA_Internal;
-
- if (!FD->isInline())
+ if (!FD->isInlined())
return External;
if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
@@ -285,8 +277,16 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
return CodeGenModule::GVA_C99Inline;
}
- // C++ inline semantics
- assert(Features.CPlusPlus && "Must be in C++ mode");
+ // C++0x [temp.explicit]p9:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
+ if (FD->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return CodeGenModule::GVA_C99Inline;
+
return CodeGenModule::GVA_CXXInline;
}
@@ -601,6 +601,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ PrettyStackTraceDecl CrashInfo((ValueDecl *)D, D->getLocation(),
+ Context.getSourceManager(),
+ "Generating code for declaration");
+
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
EmitCXXConstructor(CD, GD.getCtorType());
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))
@@ -949,7 +953,7 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
return CodeGenModule::GVA_StrongExternal;
case TSK_ExplicitInstantiationDeclaration:
- assert(false && "Variable should not be instantiated");
+ llvm::llvm_unreachable("Variable should not be instantiated");
// Fall through to treat this like any other instantiation.
case TSK_ImplicitInstantiation:
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index dedf824ef9fd..d43d13e26bbb 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -180,7 +180,7 @@ static const llvm::Type* getTypeForFormat(llvm::LLVMContext &VMContext,
}
const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
- const clang::Type &Ty = *Context.getCanonicalType(T);
+ const clang::Type &Ty = *Context.getCanonicalType(T).getTypePtr();
switch (Ty.getTypeClass()) {
#define TYPE(Class, Base)
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 2e6034bbcd97..a5b34527969b 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -52,7 +52,8 @@ namespace {
void mangleGuardVariable(const VarDecl *D);
void mangleCXXVtable(const CXXRecordDecl *RD);
- void mangleCXXRtti(const CXXRecordDecl *RD);
+ void mangleCXXVTT(const CXXRecordDecl *RD);
+ void mangleCXXRtti(QualType Ty);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
@@ -114,6 +115,7 @@ namespace {
}
static bool isInCLinkageSpecification(const Decl *D) {
+ D = D->getCanonicalDecl();
for (const DeclContext *DC = D->getDeclContext();
!DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
@@ -204,10 +206,17 @@ void CXXNameMangler::mangleCXXVtable(const CXXRecordDecl *RD) {
mangleName(RD);
}
-void CXXNameMangler::mangleCXXRtti(const CXXRecordDecl *RD) {
+void CXXNameMangler::mangleCXXVTT(const CXXRecordDecl *RD) {
+ // <special-name> ::= TT <type> # VTT structure
+ Out << "_ZTT";
+ mangleName(RD);
+}
+
+void CXXNameMangler::mangleCXXRtti(QualType Ty) {
// <special-name> ::= TI <type> # typeinfo structure
Out << "_ZTI";
- mangleName(RD);
+
+ mangleType(Ty);
}
void CXXNameMangler::mangleGuardVariable(const VarDecl *D) {
@@ -1355,7 +1364,7 @@ namespace clang {
"Mangling declaration");
CXXNameMangler Mangler(Context, os);
- if (!Mangler.mangle(cast<NamedDecl>(D->getCanonicalDecl())))
+ if (!Mangler.mangle(D))
return false;
os.flush();
@@ -1424,10 +1433,10 @@ namespace clang {
os.flush();
}
- void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD,
+ void mangleCXXRtti(MangleContext &Context, QualType Ty,
llvm::raw_ostream &os) {
CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXRtti(RD);
+ Mangler.mangleCXXRtti(Ty);
os.flush();
}
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
index 2cdb4e23919d..7f46a106f32a 100644
--- a/lib/CodeGen/Mangle.h
+++ b/lib/CodeGen/Mangle.h
@@ -65,7 +65,9 @@ namespace clang {
llvm::raw_ostream &os);
void mangleCXXVtable(MangleContext &Context, const CXXRecordDecl *RD,
llvm::raw_ostream &os);
- void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD,
+ void mangleCXXVTT(MangleContext &Context, const CXXRecordDecl *RD,
+ llvm::raw_ostream &os);
+ void mangleCXXRtti(MangleContext &Context, QualType T,
llvm::raw_ostream &os);
void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D,
CXXCtorType Type, llvm::raw_ostream &os);
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index c9d0b266d1cc..808c31c64828 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -12,8 +12,8 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Driver.h" // FIXME: Remove?
-#include "clang/Driver/DriverDiagnostic.h" // FIXME: Remove?
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/HostInfo.h"
@@ -22,9 +22,11 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Process.h"
#include "InputInfo.h"
#include "ToolChains.h"
@@ -32,13 +34,6 @@
using namespace clang::driver;
using namespace clang::driver::tools;
-static const char *MakeFormattedString(const ArgList &Args,
- const llvm::format_object_base &Fmt) {
- llvm::SmallString<256> Str;
- llvm::raw_svector_ostream(Str) << Fmt;
- return Args.MakeArgString(Str.str());
-}
-
/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
@@ -203,6 +198,10 @@ void Clang::AddPreprocessingOptions(const Driver &D,
// those options. :(
Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
options::OPT_Xpreprocessor);
+
+ // -I- is a deprecated GCC feature, reject it.
+ if (Arg *A = Args.getLastArg(options::OPT_I_))
+ D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
@@ -417,8 +416,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- // FIXME: This needs to change to use a clang-cc option, and set the attribute
- // on functions.
if (!Args.hasFlag(options::OPT_mred_zone,
options::OPT_mno_red_zone,
true) ||
@@ -426,8 +423,6 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("--disable-red-zone");
- // FIXME: This needs to change to use a clang-cc option, and set the attribute
- // on functions.
if (Args.hasFlag(options::OPT_msoft_float,
options::OPT_mno_soft_float,
false))
@@ -507,6 +502,57 @@ static bool needsExceptions(const ArgList &Args, types::ID InputType,
}
}
+/// getEffectiveClangTriple - Get the "effective" target triple, which is the
+/// triple for the target but with the OS version potentially modified for
+/// Darwin's -mmacosx-version-min.
+static std::string getEffectiveClangTriple(const Driver &D,
+ const ToolChain &TC,
+ const ArgList &Args) {
+ llvm::Triple Triple(getLLVMTriple(TC, Args));
+
+ if (Triple.getOS() != llvm::Triple::Darwin) {
+ // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+ // non-Darwin.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+ options::OPT_miphoneos_version_min_EQ))
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return Triple.getTriple();
+ }
+
+ // If -mmacosx-version-min=10.3.9 is specified, change the effective triple
+ // from being something like powerpc-apple-darwin9 to powerpc-apple-darwin7.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ)) {
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Major, Minor, Micro,
+ HadExtra) || HadExtra ||
+ Major != 10)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ // Mangle the MacOS version min number into the Darwin number: e.g. 10.3.9
+ // is darwin7.9.
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin" << Minor + 4 << "." << Micro;
+ Triple.setOSName(Str.str());
+ } else if (Arg *A = Args.getLastArg(options::OPT_miphoneos_version_min_EQ)) {
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Major, Minor, Micro,
+ HadExtra) || HadExtra)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ // Mangle the iPhoneOS version number into the Darwin number: e.g. 2.0 is 2
+ // -> 9.2.0.
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin9." << Major << "." << Minor;
+ Triple.setOSName(Str.str());
+ }
+
+ return Triple.getTriple();
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
const InputInfo &Output,
@@ -518,12 +564,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ // Add the "effective" target triple.
CmdArgs.push_back("-triple");
+ std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
- const char *TripleStr =
- Args.MakeArgString(getLLVMTriple(getToolChain(), Args));
- CmdArgs.push_back(TripleStr);
-
+ // Select the appropriate action.
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
@@ -606,9 +652,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// issue is that llvm-gcc translates these options based on
// the values in cc1, whereas we are processing based on
// the driver arguments.
- //
- // FIXME: This is currently broken for -f flags when -fno
- // variants are present.
// This comes from the default translation the driver + cc1
// would do to enable flag_pic.
@@ -661,8 +704,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--debug-pass=Structure");
if (Args.hasArg(options::OPT_fdebug_pass_arguments))
CmdArgs.push_back("--debug-pass=Arguments");
- // FIXME: set --inline-threshhold=50 if (optimize_size || optimize
- // < 3)
+ if (!Args.hasFlag(options::OPT_fmerge_all_constants,
+ options::OPT_fno_merge_all_constants))
+ CmdArgs.push_back("--no-merge-all-constants");
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
@@ -714,9 +758,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue(Args));
}
- // FIXME: Add --stack-protector-buffer-size=<xxx> on
- // -fstack-protect.
-
Arg *Unsupported;
if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
(Unsupported = Args.getLastArg(options::OPT_MQ)) ||
@@ -726,8 +767,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_v);
Args.AddLastArg(CmdArgs, options::OPT_P);
- Args.AddLastArg(CmdArgs, options::OPT_mmacosx_version_min_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_miphoneos_version_min_EQ);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
// Special case debug options to only pass -g to clang. This is
@@ -736,7 +775,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-g");
Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
- Args.AddLastArg(CmdArgs, options::OPT_nostdclanginc);
+ Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
Args.AddLastArg(CmdArgs, options::OPT_isysroot);
@@ -759,7 +798,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
@@ -770,9 +811,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
if (Std->getOption().matches(options::OPT_ansi))
if (types::isCXX(InputType))
- CmdArgs.push_back("-std=c++98");
+ CmdArgs.push_back("-std=c++98");
else
- CmdArgs.push_back("-std=c89");
+ CmdArgs.push_back("-std=c89");
else
Std->render(Args, CmdArgs);
@@ -794,10 +835,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT__relocatable_pch, true))
CmdArgs.push_back("--relocatable-pch");
- if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
- CmdArgs.push_back("-fconstant-string-class");
- CmdArgs.push_back(A->getValue(Args));
- }
+ if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+ CmdArgs.push_back("-fconstant-string-class");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // Pass -fmessage-length=.
+ if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
+ A->render(Args, CmdArgs);
+ } else {
+ // If -fmessage-length=N was not specified, determine whether this is a
+ // terminal and, if so, implicitly define -fmessage-length appropriately.
+ unsigned N = llvm::sys::Process::StandardErrColumns();
+ CmdArgs.push_back("-fmessage-length");
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N)));
+ }
// Forward -f options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
@@ -805,7 +857,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fgnu_runtime);
Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions);
- Args.AddLastArg(CmdArgs, options::OPT_fmessage_length_EQ);
Args.AddLastArg(CmdArgs, options::OPT_fms_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fnext_runtime);
Args.AddLastArg(CmdArgs, options::OPT_fno_caret_diagnostics);
@@ -871,9 +922,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsigned-char=0");
}
- // -fno-pascal-strings is default, only pass non-default. If the
- // -tool chain happened to translate to -mpascal-strings, we want to
- // -back translate here.
+ // -fno-pascal-strings is default, only pass non-default. If the tool chain
+ // happened to translate to -mpascal-strings, we want to back translate here.
//
// FIXME: This is gross; that translation should be pulled from the
// tool chain.
@@ -905,9 +955,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
options::OPT_fno_diagnostics_show_option))
CmdArgs.push_back("-fdiagnostics-show-option");
- if (!Args.hasFlag(options::OPT_fcolor_diagnostics,
- options::OPT_fno_color_diagnostics))
- CmdArgs.push_back("-fno-color-diagnostics");
+
+ // Color diagnostics are the default, unless the terminal doesn't support
+ // them.
+ if (Args.hasFlag(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics) &&
+ llvm::sys::Process::StandardErrHasColors())
+ CmdArgs.push_back("-fcolor-diagnostics");
+
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
@@ -979,6 +1034,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
II.getInputArg().renderAsInput(Args, CmdArgs);
}
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
@@ -1667,23 +1724,18 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
static bool isSourceSuffix(const char *Str) {
// match: 'C', 'CPP', 'c', 'cc', 'cp', 'c++', 'cpp', 'cxx', 'm',
// 'mm'.
- switch (strlen(Str)) {
- default:
- return false;
- case 1:
- return (memcmp(Str, "C", 1) == 0 ||
- memcmp(Str, "c", 1) == 0 ||
- memcmp(Str, "m", 1) == 0);
- case 2:
- return (memcmp(Str, "cc", 2) == 0 ||
- memcmp(Str, "cp", 2) == 0 ||
- memcmp(Str, "mm", 2) == 0);
- case 3:
- return (memcmp(Str, "CPP", 3) == 0 ||
- memcmp(Str, "c++", 3) == 0 ||
- memcmp(Str, "cpp", 3) == 0 ||
- memcmp(Str, "cxx", 3) == 0);
- }
+ return llvm::StringSwitch<bool>(Str)
+ .Case("C", true)
+ .Case("c", true)
+ .Case("m", true)
+ .Case("cc", true)
+ .Case("cp", true)
+ .Case("mm", true)
+ .Case("CPP", true)
+ .Case("c++", true)
+ .Case("cpp", true)
+ .Case("cxx", true)
+ .Default(false);
}
// FIXME: Can we tablegen this?
@@ -1861,7 +1913,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
// Adding all arguments doesn't make sense here but this is what
// gcc does.
Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
- "-macosx_version_min");
+ "-macosx_version_min");
Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
"-iphoneos_version_min");
Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
@@ -2137,10 +2189,10 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
}
void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -2167,15 +2219,15 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getHost().getDriver();
ArgStringList CmdArgs;
if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ (!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
CmdArgs.push_back("_start");
}
@@ -2212,14 +2264,13 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
-// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
}
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/opt/gcc4/lib/gcc/%s/4.2.4",
- getToolChain().getTripleString().c_str())));
+ CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
+ + getToolChain().getTripleString()
+ + "/4.2.4"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2307,7 +2358,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ (!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
@@ -2345,9 +2396,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc-lib/%s/3.3.5",
- getToolChain().getTripleString().c_str())));
+ std::string Triple = getToolChain().getTripleString();
+ if (Triple.substr(0, 6) == "x86_64")
+ Triple.replace(0, 6, "amd64");
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
+ "/3.3.5"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2547,10 +2600,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
// When building 32-bit code on DragonFly/pc64, we have to explicitly
@@ -2678,7 +2731,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-lthread_xu");
+ CmdArgs.push_back("-lpthread");
if (!Args.hasArg(options::OPT_nolibc)) {
CmdArgs.push_back("-lc");
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index eee8c19c2776..c616c6a5bf4b 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -9,6 +9,7 @@
#include "clang/Driver/Types.h"
+#include "llvm/ADT/StringSwitch.h"
#include <string.h>
#include <cassert>
@@ -102,51 +103,42 @@ bool types::isCXX(ID Id) {
}
types::ID types::lookupTypeForExtension(const char *Ext) {
- unsigned N = strlen(Ext);
-
- switch (N) {
- case 1:
- if (memcmp(Ext, "c", 1) == 0) return TY_C;
- if (memcmp(Ext, "i", 1) == 0) return TY_PP_C;
- if (memcmp(Ext, "m", 1) == 0) return TY_ObjC;
- if (memcmp(Ext, "M", 1) == 0) return TY_ObjCXX;
- if (memcmp(Ext, "h", 1) == 0) return TY_CHeader;
- if (memcmp(Ext, "C", 1) == 0) return TY_CXX;
- if (memcmp(Ext, "H", 1) == 0) return TY_CXXHeader;
- if (memcmp(Ext, "f", 1) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "F", 1) == 0) return TY_Fortran;
- if (memcmp(Ext, "s", 1) == 0) return TY_PP_Asm;
- if (memcmp(Ext, "S", 1) == 0) return TY_Asm;
- case 2:
- if (memcmp(Ext, "ii", 2) == 0) return TY_PP_CXX;
- if (memcmp(Ext, "mi", 2) == 0) return TY_PP_ObjC;
- if (memcmp(Ext, "mm", 2) == 0) return TY_ObjCXX;
- if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "cp", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "hh", 2) == 0) return TY_CXXHeader;
- break;
- case 3:
- if (memcmp(Ext, "ads", 3) == 0) return TY_Ada;
- if (memcmp(Ext, "adb", 3) == 0) return TY_Ada;
- if (memcmp(Ext, "ast", 3) == 0) return TY_AST;
- if (memcmp(Ext, "cxx", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "cpp", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "CPP", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "cXX", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "for", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "FOR", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "fpp", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "FPP", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "f90", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "f95", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "F90", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "F95", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "mii", 3) == 0) return TY_PP_ObjCXX;
- break;
- }
-
- return TY_INVALID;
+ return llvm::StringSwitch<types::ID>(Ext)
+ .Case("c", TY_C)
+ .Case("i", TY_PP_C)
+ .Case("m", TY_ObjC)
+ .Case("M", TY_ObjCXX)
+ .Case("h", TY_CHeader)
+ .Case("C", TY_CXX)
+ .Case("H", TY_CXXHeader)
+ .Case("f", TY_PP_Fortran)
+ .Case("F", TY_Fortran)
+ .Case("s", TY_PP_Asm)
+ .Case("S", TY_Asm)
+ .Case("ii", TY_PP_CXX)
+ .Case("mi", TY_PP_ObjC)
+ .Case("mm", TY_ObjCXX)
+ .Case("cc", TY_CXX)
+ .Case("CC", TY_CXX)
+ .Case("cp", TY_CXX)
+ .Case("hh", TY_CXXHeader)
+ .Case("ads", TY_Ada)
+ .Case("adb", TY_Ada)
+ .Case("ast", TY_AST)
+ .Case("cxx", TY_CXX)
+ .Case("cpp", TY_CXX)
+ .Case("CPP", TY_CXX)
+ .Case("CXX", TY_CXX)
+ .Case("for", TY_PP_Fortran)
+ .Case("FOR", TY_PP_Fortran)
+ .Case("fpp", TY_Fortran)
+ .Case("FPP", TY_Fortran)
+ .Case("f90", TY_PP_Fortran)
+ .Case("f95", TY_PP_Fortran)
+ .Case("F90", TY_Fortran)
+ .Case("F95", TY_Fortran)
+ .Case("mii", TY_PP_ObjCXX)
+ .Default(TY_INVALID);
}
types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 8d76680f6f92..9a30f59465f8 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -400,11 +400,6 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<parameter> " << PVD->getNameAsString() << "\n";
break;
}
- case Decl::OriginalParmVar: {
- OriginalParmVarDecl* OPVD = cast<OriginalParmVarDecl>(*I);
- Out << "<original parameter> " << OPVD->getNameAsString() << "\n";
- break;
- }
case Decl::ObjCProperty: {
ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
Out << "<objc property> " << OPD->getNameAsString() << "\n";
@@ -457,6 +452,8 @@ class RecordLayoutDumper : public ASTConsumer {
// Dump (non-virtual) bases
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
if (I->isVirtual())
continue;
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 55f274005909..049f3bd3ea14 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -29,7 +29,6 @@
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 25316bed9fb4..c0b4ebaab03b 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -241,11 +241,9 @@ bool getVisualStudioDir(std::string &path) {
return(false);
}
-void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
- const llvm::Triple &triple) {
+void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
// FIXME: temporary hack: hard-coded paths.
llvm::Triple::OSType os = triple.getOS();
-
switch (os) {
case llvm::Triple::Win32:
{
@@ -276,162 +274,186 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
}
}
break;
- case llvm::Triple::Cygwin:
- if (Lang.CPlusPlus) {
- AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
- System, false, false, false);
- AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
- System, false, false, false);
- }
- AddPath("/usr/include", System, false, false, false);
- break;
case llvm::Triple::MinGW64:
- if (Lang.CPlusPlus) { // I'm guessing here.
- // Try gcc 4.4.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
- // Try gcc 4.3.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
- }
- // Fall through.
case llvm::Triple::MinGW32:
- if (Lang.CPlusPlus) {
- // Try gcc 4.4.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
- // Try gcc 4.3.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
- }
AddPath("c:/mingw/include", System, true, false, false);
break;
default:
- if (Lang.CPlusPlus) {
- switch (os) {
- case llvm::Triple::Darwin:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "i686-apple-darwin10",
- "i686-apple-darwin10/x86_64",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "i686-apple-darwin8",
- "i686-apple-darwin8",
- triple);
- break;
- case llvm::Triple::Linux:
- // Ubuntu 7.10 - Gutsy Gibbon
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
- // Ubuntu 9.04
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
- "x86_64-linux-gnu/32",
- "x86_64-linux-gnu",
- triple);
- // Fedora 8
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // Fedora 9
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // Fedora 10
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // openSUSE 11.1 32 bit
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
- // openSUSE 11.1 64 bit
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "x86_64-suse-linux/32",
- "x86_64-suse-linux",
- triple);
- // openSUSE 11.2
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "x86_64-suse-linux",
- "x86_64-suse-linux",
- triple);
- // Arch Linux 2008-06-24
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "x86_64-unknown-linux-gnu",
- "x86_64-unknown-linux-gnu",
- triple);
- // Gentoo x86 2009.1 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Gentoo x86 2009.0 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Gentoo x86 2008.0 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Ubuntu 8.10
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-pc-linux-gnu",
- "i486-pc-linux-gnu",
- triple);
- // Ubuntu 9.04
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
- // Gentoo amd64 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- break;
- case llvm::Triple::FreeBSD:
- // DragonFly
- AddPath("/usr/include/c++/4.1", System, true, false, false);
- // FreeBSD
- AddPath("/usr/include/c++/4.2", System, true, false, false);
- break;
- case llvm::Triple::Solaris:
- // Solaris - Fall though..
- case llvm::Triple::AuroraUX:
- // AuroraUX
- AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
- "i386-pc-solaris2.11",
- "i386-pc-solaris2.11",
- triple);
- break;
- default:
- break;
- }
- }
break;
}
AddPath("/usr/local/include", System, false, false, false);
AddPath("/usr/include", System, false, false, false);
+}
+
+void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
+ llvm::Triple::OSType os = triple.getOS();
+ // FIXME: temporary hack: hard-coded paths.
+ switch (os) {
+ case llvm::Triple::Cygwin:
+ AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
+ System, true, false, false);
+ AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
+ System, true, false, false);
+ break;
+ case llvm::Triple::MinGW64:
+ // Try gcc 4.4.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
+ // Try gcc 4.3.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
+ // Fall through.
+ case llvm::Triple::MinGW32:
+ // Try gcc 4.4.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
+ // Try gcc 4.3.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+ break;
+ case llvm::Triple::Darwin:
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "i686-apple-darwin10",
+ "i686-apple-darwin10/x86_64",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+ "i686-apple-darwin8",
+ "i686-apple-darwin8",
+ triple);
+ break;
+ case llvm::Triple::Linux:
+ // Ubuntu 7.10 - Gutsy Gibbon
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
+ "i486-linux-gnu",
+ "i486-linux-gnu",
+ triple);
+ // Ubuntu 9.04
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
+ "x86_64-linux-gnu/32",
+ "x86_64-linux-gnu",
+ triple);
+ // Fedora 8
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // Fedora 9
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // Fedora 10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // openSUSE 11.1 32 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i586-suse-linux",
+ "i586-suse-linux",
+ triple);
+ // openSUSE 11.1 64 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "x86_64-suse-linux/32",
+ "x86_64-suse-linux",
+ triple);
+ // openSUSE 11.2
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "i586-suse-linux",
+ "i586-suse-linux",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "x86_64-suse-linux",
+ "x86_64-suse-linux",
+ triple);
+ // Arch Linux 2008-06-24
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "x86_64-unknown-linux-gnu",
+ "x86_64-unknown-linux-gnu",
+ triple);
+ // Gentoo x86 2009.1 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Gentoo x86 2009.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Gentoo x86 2008.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Ubuntu 8.10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-pc-linux-gnu",
+ "i486-pc-linux-gnu",
+ triple);
+ // Ubuntu 9.04
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-linux-gnu",
+ "i486-linux-gnu",
+ triple);
+ // Gentoo amd64 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Exherbo (2009-10-26)
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.4.2",
+ "x86_64-pc-linux-gnu/32",
+ "x86_64-pc-linux-gnu",
+ triple);
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.4.2",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ break;
+ case llvm::Triple::FreeBSD:
+ // DragonFly
+ AddPath("/usr/include/c++/4.1", System, true, false, false);
+ // FreeBSD
+ AddPath("/usr/include/c++/4.2", System, true, false, false);
+ break;
+ case llvm::Triple::Solaris:
+ // Solaris - Fall though..
+ case llvm::Triple::AuroraUX:
+ // AuroraUX
+ AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
+ "i386-pc-solaris2.11",
+ "i386-pc-solaris2.11",
+ triple);
+ break;
+ default:
+ break;
+ }
+}
+
+void InitHeaderSearch::AddDefaultFrameworkIncludePaths(const llvm::Triple &triple) {
+ llvm::Triple::OSType os = triple.getOS();
+ if (os != llvm::Triple::Darwin)
+ return;
AddPath("/System/Library/Frameworks", System, true, false, true);
AddPath("/Library/Frameworks", System, true, false, true);
}
+void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple) {
+ AddDefaultCIncludePaths(triple);
+ AddDefaultFrameworkIncludePaths(triple);
+ if (Lang.CPlusPlus)
+ AddDefaultCPlusPlusIncludePaths(triple);
+}
+
void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) {
AddEnvVarPaths("CPATH");
if (Lang.CPlusPlus && Lang.ObjC1)
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index b1a0a5ee8d51..ec5c1061bb93 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -17,8 +17,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/System/Path.h"
-
-namespace clang {
+using namespace clang;
// Append a #define line to Buf for Macro. Macro should be of the form XXX,
// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
@@ -346,27 +345,15 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
DefineBuiltinMacro(Buf, "__CHAR_BIT__=8");
- unsigned IntMaxWidth;
- const char *IntMaxSuffix;
- if (TI.getIntMaxType() == TargetInfo::SignedLongLong) {
- IntMaxWidth = TI.getLongLongWidth();
- IntMaxSuffix = "LL";
- } else if (TI.getIntMaxType() == TargetInfo::SignedLong) {
- IntMaxWidth = TI.getLongWidth();
- IntMaxSuffix = "L";
- } else {
- assert(TI.getIntMaxType() == TargetInfo::SignedInt);
- IntMaxWidth = TI.getIntWidth();
- IntMaxSuffix = "";
- }
-
DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf);
DefineTypeSize("__SHRT_MAX__", TI.getShortWidth(), "", true, Buf);
DefineTypeSize("__INT_MAX__", TI.getIntWidth(), "", true, Buf);
DefineTypeSize("__LONG_MAX__", TI.getLongWidth(), "L", true, Buf);
DefineTypeSize("__LONG_LONG_MAX__", TI.getLongLongWidth(), "LL", true, Buf);
DefineTypeSize("__WCHAR_MAX__", TI.getWCharWidth(), "", true, Buf);
- DefineTypeSize("__INTMAX_MAX__", IntMaxWidth, IntMaxSuffix, true, Buf);
+ TargetInfo::IntType IntMaxType = TI.getIntMaxType();
+ DefineTypeSize("__INTMAX_MAX__", TI.getTypeWidth(IntMaxType),
+ TI.getTypeConstantSuffix(IntMaxType), true, Buf);
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf);
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf);
@@ -455,8 +442,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
-bool InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions& InitOpts) {
+bool clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions &InitOpts,
+ bool undef_macros) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -464,8 +452,9 @@ bool InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
- PredefineBuffer);
+ if (!undef_macros)
+ InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
+ PredefineBuffer);
// Add on the predefines from the driver. Wrap in a #line directive to report
// that they come from the command line.
@@ -504,5 +493,3 @@ bool InitializePreprocessor(Preprocessor &PP,
// Once we've read this, we're done.
return false;
}
-
-} // namespace clang
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 9c6059b1c7c0..26f426ba329b 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -32,6 +32,7 @@
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <iterator>
#include <cstdio>
@@ -2104,7 +2105,13 @@ void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
}
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i,
+ Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
+ Record, Idx));
}
void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2197,6 +2204,25 @@ QualType PCHReader::GetType(pch::TypeID ID) {
return TypesLoaded[Index].withFastQualifiers(FastQuals);
}
+TemplateArgumentLocInfo
+PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const RecordData &Record,
+ unsigned &Index) {
+ switch (Kind) {
+ case TemplateArgument::Expression:
+ return ReadDeclExpr();
+ case TemplateArgument::Type:
+ return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ return TemplateArgumentLocInfo();
+ }
+ llvm::llvm_unreachable("unexpected template argument loc");
+ return TemplateArgumentLocInfo();
+}
+
Decl *PCHReader::GetDecl(pch::DeclID ID) {
if (ID == 0)
return 0;
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index d1cb461640b7..b9ece21f74c3 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -52,7 +52,6 @@ namespace {
void VisitVarDecl(VarDecl *VD);
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
- void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
void VisitBlockDecl(BlockDecl *BD);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
@@ -107,9 +106,9 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
// set the underlying type of the typedef *before* we try to read
// the type associated with the TypedefDecl.
VisitNamedDecl(TD);
- TD->setUnderlyingType(Reader.GetType(Record[Idx + 1]));
- TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr());
- Idx += 2;
+ uint64_t TypeData = Record[Idx++];
+ TD->setTypeDeclaratorInfo(Reader.GetDeclaratorInfo(Record, Idx));
+ TD->setTypeForDecl(Reader.GetType(TypeData).getTypePtr());
}
void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
@@ -163,7 +162,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setPreviousDeclaration(
cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
- FD->setInline(Record[Idx++]);
+ FD->setInlineSpecified(Record[Idx++]);
FD->setVirtualAsWritten(Record[Idx++]);
FD->setPure(Record[Idx++]);
FD->setHasInheritedPrototype(Record[Idx++]);
@@ -370,11 +369,6 @@ void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
}
-void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
- VisitParmVarDecl(PD);
- PD->setOriginalType(Reader.GetType(Record[Idx++]));
-}
-
void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
VisitDecl(AD);
AD->setAsmString(cast<StringLiteral>(Reader.ReadDeclExpr()));
@@ -618,7 +612,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = Context->getTranslationUnitDecl();
break;
case pch::DECL_TYPEDEF:
- D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
+ D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case pch::DECL_ENUM:
D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), 0);
@@ -696,10 +690,6 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
VarDecl::None, 0);
break;
- case pch::DECL_ORIGINAL_PARM_VAR:
- D = OriginalParmVarDecl::Create(*Context, 0, SourceLocation(), 0,
- QualType(),0, QualType(), VarDecl::None, 0);
- break;
case pch::DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
break;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index 4b9496e00f8b..01af67dd50a1 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -347,6 +347,8 @@ unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ // FIXME: read qualifier
+ // FIXME: read explicit template arguments
return 0;
}
@@ -422,7 +424,7 @@ unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->setArgument(cast<Expr>(StmtStack.back()));
++Idx;
} else {
- E->setArgument(Reader.GetType(Record[Idx++]));
+ E->setArgument(Reader.GetDeclaratorInfo(Record, Idx));
}
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index fb48df332121..de56166125ed 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -368,7 +368,11 @@ void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
}
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- Writer.AddSourceLocation(TL.getNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ Writer.AddTemplateArgumentLoc(TL.getArgLoc(i), Record);
}
void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
@@ -589,7 +593,6 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(DECL_VAR);
RECORD(DECL_IMPLICIT_PARAM);
RECORD(DECL_PARM_VAR);
- RECORD(DECL_ORIGINAL_PARM_VAR);
RECORD(DECL_FILE_SCOPE_ASM);
RECORD(DECL_BLOCK);
RECORD(DECL_CONTEXT_LEXICAL);
@@ -2106,6 +2109,23 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
Record.push_back(SID);
}
+void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordData &Record) {
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Expression:
+ AddStmt(Arg.getLocInfo().getAsExpr());
+ break;
+ case TemplateArgument::Type:
+ AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
+ break;
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ break;
+ }
+}
+
void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) {
if (DInfo == 0) {
AddTypeRef(QualType(), Record);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index fbd9929e49d7..8997e661a5a1 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -55,7 +55,6 @@ namespace {
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
- void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
void VisitBlockDecl(BlockDecl *D);
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
@@ -107,7 +106,7 @@ void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
VisitTypeDecl(D);
- Writer.AddTypeRef(D->getUnderlyingType(), Record);
+ Writer.AddDeclaratorInfo(D->getTypeDeclaratorInfo(), Record);
Code = pch::DECL_TYPEDEF;
}
@@ -162,7 +161,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Writer.AddStmt(D->getBody());
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
- Record.push_back(D->isInline());
+ Record.push_back(D->isInlineSpecified());
Record.push_back(D->isVirtualAsWritten());
Record.push_back(D->isPure());
Record.push_back(D->hasInheritedPrototype());
@@ -390,13 +389,6 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
}
-void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
- VisitParmVarDecl(D);
- Writer.AddTypeRef(D->getOriginalType(), Record);
- Code = pch::DECL_ORIGINAL_PARM_VAR;
- AbbrevToUse = 0;
-}
-
void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getAsmString());
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 9497f973f6bc..78a56db7edcd 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -314,6 +314,8 @@ void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
+ // FIXME: write qualifier
+ // FIXME: write explicit template arguments
Code = pch::EXPR_DECL_REF;
}
@@ -382,7 +384,7 @@ void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
VisitExpr(E);
Record.push_back(E->isSizeOf());
if (E->isArgumentType())
- Writer.AddTypeRef(E->getArgumentType(), Record);
+ Writer.AddDeclaratorInfo(E->getArgumentTypeInfo(), Record);
else {
Record.push_back(0);
Writer.WriteSubStmt(E->getArgumentExpr());
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index f3cb20619ed5..630a093a4bf6 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -66,7 +66,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
OS << ' ';
// Make sure we have enough space in the spelling buffer.
- if (I->getLength() < SpellingBuffer.size())
+ if (I->getLength() > SpellingBuffer.size())
SpellingBuffer.resize(I->getLength());
const char *Buffer = SpellingBuffer.data();
unsigned SpellingLen = PP.getSpelling(*I, Buffer);
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 0ea0a58d5239..24ad69e3e0d3 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -2569,7 +2569,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// Build sizeof(returnType)
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
- returnType,
+ Context->getTrivialDeclaratorInfo(returnType),
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
@@ -2609,10 +2609,12 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
// typedef struct objc_object Protocol;
QualType RewriteObjC::getProtocolType() {
if (!ProtocolTypeDecl) {
+ DeclaratorInfo *DInfo
+ = Context->getTrivialDeclaratorInfo(Context->getObjCIdType());
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
SourceLocation(),
&Context->Idents.get("Protocol"),
- Context->getObjCIdType());
+ DInfo);
}
return Context->getTypeDeclType(ProtocolTypeDecl);
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 14769c187393..b1d8800369e5 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -37,6 +38,12 @@ static const enum llvm::raw_ostream::Colors savedColor =
/// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
+ const DiagnosticOptions &diags)
+ : OS(os), LangOpts(0), DiagOpts(&diags),
+ LastCaretDiagnosticWasNote(false) {
+}
+
void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
if (Loc.isInvalid()) return;
@@ -46,7 +53,7 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
// Print out the other include frames first.
PrintIncludeStack(PLoc.getIncludeLoc(), SM);
- if (ShowLocation)
+ if (DiagOpts->ShowLocation)
OS << "In file included from " << PLoc.getFilename()
<< ':' << PLoc.getLine() << ":\n";
else
@@ -281,13 +288,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
Ranges[i] = SourceRange(S, E);
}
- if (ShowLocation) {
+ if (DiagOpts->ShowLocation) {
std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc);
// Emit the file/line/column that this expansion came from.
OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':'
<< SM.getLineNumber(IInfo.first, IInfo.second) << ':';
- if (ShowColumn)
+ if (DiagOpts->ShowColumn)
OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':';
OS << ' ';
}
@@ -370,13 +377,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// produce easily machine parsable output. Add a space before the source line
// and the caret to make it trivial to tell the main diagnostic line from what
// the user is intended to see.
- if (PrintRangeInfo) {
+ if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
std::string FixItInsertionLine;
- if (NumHints && PrintFixItInfo) {
+ if (NumHints && DiagOpts->ShowFixits) {
for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints;
Hint != LastHint; ++Hint) {
if (Hint->InsertionLoc.isValid()) {
@@ -417,20 +424,20 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// Emit what we have computed.
OS << SourceLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true);
OS << CaretLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
if (!FixItInsertionLine.empty()) {
- if (UseColors)
+ if (DiagOpts->ShowColors)
// Print fixit line in color
OS.changeColor(fixitColor, false);
- if (PrintRangeInfo)
+ if (DiagOpts->ShowSourceRanges)
OS << ' ';
OS << FixItInsertionLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
}
@@ -627,15 +634,15 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
}
// Compute the column number.
- if (ShowLocation) {
- if (UseColors)
+ if (DiagOpts->ShowLocation) {
+ if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
OS << PLoc.getFilename() << ':' << LineNo << ':';
- if (ShowColumn)
+ if (DiagOpts->ShowColumn)
if (unsigned ColNo = PLoc.getColumn())
OS << ColNo << ':';
- if (PrintRangeInfo && Info.getNumRanges()) {
+ if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
FileID CaretFileID =
SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
bool PrintedRange = false;
@@ -679,12 +686,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
OS << ':';
}
OS << ' ';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
}
- if (UseColors) {
+ if (DiagOpts->ShowColors) {
// Print diagnostic category in bold and color
switch (Level) {
case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
@@ -703,20 +710,20 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
case Diagnostic::Fatal: OS << "fatal error: "; break;
}
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
llvm::SmallString<100> OutStr;
Info.FormatDiagnostic(OutStr);
- if (PrintDiagnosticOption)
+ if (DiagOpts->ShowOptionNames)
if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
OutStr += " [-W";
OutStr += Opt;
OutStr += ']';
}
- if (UseColors) {
+ if (DiagOpts->ShowColors) {
// Print warnings, errors and fatal errors in bold, no color
switch (Level) {
case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
@@ -726,17 +733,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
}
}
- if (MessageLength) {
+ if (DiagOpts->MessageLength) {
// We will be word-wrapping the error message, so compute the
// column number where we currently are (after printing the
// location information).
unsigned Column = OS.tell() - StartOfLocationInfo;
- PrintWordWrapped(OS, OutStr, MessageLength, Column);
+ PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
} else {
OS.write(OutStr.begin(), OutStr.size());
}
OS << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
// If caret diagnostics are enabled and we have location, we want to
@@ -745,7 +752,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics.
- if (CaretDiagnostics && Info.getLocation().isValid() &&
+ if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
Info.getNumCodeModificationHints())) {
@@ -772,7 +779,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
Info.getCodeModificationHints(),
Info.getNumCodeModificationHints(),
- MessageLength);
+ DiagOpts->MessageLength);
}
OS.flush();
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 6c874f4b7bb5..e63291b2af90 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -35,4 +35,4 @@ add_custom_target(clang-headers ALL
install(FILES ${files}
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
- DESTINATION lib/clang/${CLANG_VERSION}/include)
+ DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h
index a7020d838ec9..f79a0f4af557 100644
--- a/lib/Headers/stdint.h
+++ b/lib/Headers/stdint.h
@@ -28,7 +28,8 @@
/* If we're hosted, fall back to the system's stdint.h, which might have
* additional definitions.
*/
-#if __STDC_HOSTED__
+#if __STDC_HOSTED__ && \
+ defined(__has_include_next) && __has_include_next(<stdint.h>)
# include_next <stdint.h>
#else
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 8edd634f8af4..73b584b5205d 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -45,6 +45,9 @@ protected:
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
if (ContainsLocation(DD->getDeclaratorInfo()))
return ContainsLoc;
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+ if (ContainsLocation(TD->getTypeDeclaratorInfo()))
+ return ContainsLoc;
return CheckRange(D->getSourceRange());
}
@@ -57,11 +60,6 @@ protected:
}
template <typename T>
- bool ContainsLocation(T Node) {
- return CheckRange(Node) == ContainsLoc;
- }
-
- template <typename T>
bool isAfterLocation(T Node) {
return CheckRange(Node) == AfterLoc;
}
@@ -69,6 +67,11 @@ protected:
public:
LocResolverBase(ASTContext &ctx, SourceLocation loc)
: Ctx(ctx), Loc(loc) {}
+
+ template <typename T>
+ bool ContainsLocation(T Node) {
+ return CheckRange(Node) == ContainsLoc;
+ }
#ifndef NDEBUG
/// \brief Debugging output.
@@ -89,6 +92,7 @@ public:
StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
: LocResolverBase(ctx, loc), Parent(parent) {}
+ ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
ASTLocation VisitDeclStmt(DeclStmt *Node);
ASTLocation VisitStmt(Stmt *Node);
@@ -109,6 +113,7 @@ public:
ASTLocation VisitVarDecl(VarDecl *D);
ASTLocation VisitFunctionDecl(FunctionDecl *D);
ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
+ ASTLocation VisitTypedefDecl(TypedefDecl *D);
ASTLocation VisitDecl(Decl *D);
};
@@ -132,6 +137,25 @@ public:
} // anonymous namespace
ASTLocation
+StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+ assert(ContainsLocation(Node) &&
+ "Should visit only after verifying that loc is in range");
+
+ if (Node->isArgumentType()) {
+ DeclaratorInfo *DInfo = Node->getArgumentTypeInfo();
+ if (ContainsLocation(DInfo))
+ return ResolveInDeclarator(Parent, Node, DInfo);
+ } else {
+ Expr *SubNode = Node->getArgumentExpr();
+ if (ContainsLocation(SubNode))
+ return Visit(SubNode);
+ }
+
+ return ASTLocation(Parent, Node);
+}
+
+
+ASTLocation
StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
assert(ContainsLocation(Node) &&
"Should visit only after verifying that loc is in range");
@@ -278,6 +302,16 @@ ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
return ASTLocation(D);
}
+ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
+ assert(ContainsLocation(D) &&
+ "Should visit only after verifying that loc is in range");
+
+ if (ContainsLocation(D->getTypeDeclaratorInfo()))
+ return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeDeclaratorInfo());
+
+ return ASTLocation(D);
+}
+
ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
assert(ContainsLocation(D) &&
"Should visit only after verifying that loc is in range");
@@ -529,11 +563,40 @@ void LocResolverBase::print(Stmt *Node) {
/// \brief Returns the AST node that a source location points to.
///
ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl) {
+ ASTLocation *LastLoc) {
if (Loc.isInvalid())
return ASTLocation();
- if (RelativeToDecl)
- return DeclLocResolver(Ctx, Loc).Visit(RelativeToDecl);
+ if (LastLoc && LastLoc->isValid()) {
+ DeclContext *DC = 0;
+
+ if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
+ DC = Dcl->getDeclContext();
+ } else if (LastLoc->isStmt()) {
+ Decl *Parent = LastLoc->getParentDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
+ DC = FD;
+ else {
+ // This is needed to handle statements within an initializer.
+ // Example:
+ // void func() { long double fabsf = __builtin_fabsl(__x); }
+ // In this case, the 'parent' of __builtin_fabsl is fabsf.
+ DC = Parent->getDeclContext();
+ }
+ } else { // We have 'N_NamedRef' or 'N_Type'
+ DC = LastLoc->getParentDecl()->getDeclContext();
+ }
+ assert(DC && "Missing DeclContext");
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
+ DeclLocResolver DLocResolver(Ctx, Loc);
+
+ if (FD && FD->isThisDeclarationADefinition() &&
+ DLocResolver.ContainsLocation(FD)) {
+ return DLocResolver.VisitFunctionDecl(FD);
+ }
+ // Fall through and try the slow path...
+ // FIXME: Optimize more cases.
+ }
return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
}
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index c9a10dc02707..df712760bb25 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -15,7 +15,7 @@
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstdio>
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index e264efab9d7b..dc7d95e70118 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -974,11 +974,11 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
/// This code concatenates and consumes tokens up to the '>' token. It returns
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
-static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
- Preprocessor &PP) {
+bool Preprocessor::ConcatenateIncludeName(
+ llvm::SmallVector<char, 128> &FilenameBuffer) {
Token CurTok;
- PP.Lex(CurTok);
+ Lex(CurTok);
while (CurTok.isNot(tok::eom)) {
// Append the spelling of this token to the buffer. If there was a space
// before it, add it now.
@@ -990,7 +990,7 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
const char *BufPtr = &FilenameBuffer[PreAppendSize];
- unsigned ActualLen = PP.getSpelling(CurTok, BufPtr);
+ unsigned ActualLen = getSpelling(CurTok, BufPtr);
// If the token was spelled somewhere else, copy it into FilenameBuffer.
if (BufPtr != &FilenameBuffer[PreAppendSize])
@@ -1004,12 +1004,12 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
if (CurTok.is(tok::greater))
return false;
- PP.Lex(CurTok);
+ Lex(CurTok);
}
// If we hit the eom marker, emit an error and return true so that the caller
// knows the EOM has been read.
- PP.Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
+ Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
return true;
}
@@ -1047,7 +1047,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
// This could be a <foo/bar.h> file coming from a macro expansion. In this
// case, glue the tokens together into FilenameBuffer and interpret those.
FilenameBuffer.push_back('<');
- if (ConcatenateIncludeName(FilenameBuffer, *this))
+ if (ConcatenateIncludeName(FilenameBuffer))
return; // Found <eom> but no ">"? Diagnostic already emitted.
FilenameStart = FilenameBuffer.data();
FilenameEnd = FilenameStart + FilenameBuffer.size();
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 908385c5d392..a74396c3146c 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -71,6 +71,61 @@ struct DefinedTracker {
IdentifierInfo *TheMacro;
};
+/// EvaluateDefined - Process a 'defined(sym)' expression.
+static bool EvaluateDefined(PPValue &Result, Token &PeekTok,
+ DefinedTracker &DT, bool ValueLive, Preprocessor &PP) {
+ IdentifierInfo *II;
+ Result.setBegin(PeekTok.getLocation());
+
+ // Get the next token, don't expand it.
+ PP.LexUnexpandedToken(PeekTok);
+
+ // Two options, it can either be a pp-identifier or a (.
+ SourceLocation LParenLoc;
+ if (PeekTok.is(tok::l_paren)) {
+ // Found a paren, remember we saw it and skip it.
+ LParenLoc = PeekTok.getLocation();
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
+ // If we don't have a pp-identifier now, this is an error.
+ if ((II = PeekTok.getIdentifierInfo()) == 0) {
+ PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
+ return true;
+ }
+
+ // Otherwise, we got an identifier, is it defined to something?
+ Result.Val = II->hasMacroDefinition();
+ Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
+
+ // If there is a macro, mark it used.
+ if (Result.Val != 0 && ValueLive) {
+ MacroInfo *Macro = PP.getMacroInfo(II);
+ Macro->setIsUsed(true);
+ }
+
+ // Consume identifier.
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+
+ // If we are in parens, ensure we have a trailing ).
+ if (LParenLoc.isValid()) {
+ if (PeekTok.isNot(tok::r_paren)) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return true;
+ }
+ // Consume the ).
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ }
+
+ // Success, remember that we saw defined(X).
+ DT.State = DefinedTracker::DefinedMacro;
+ DT.TheMacro = II;
+ return false;
+}
+
/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
/// return the computed value in Result. Return true if there was an error
/// parsing. This function also returns information about the form of the
@@ -87,10 +142,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// 'defined' or if it is a macro. Note that we check here because many
// keywords are pp-identifiers, so we can't check the kind.
if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
- // If this identifier isn't 'defined' and it wasn't macro expanded, it turns
- // into a simple 0, unless it is the C++ keyword "true", in which case it
- // turns into "1".
- if (!II->isStr("defined")) {
+ if (II->isStr("defined")) {
+ // Handle "defined X" and "defined(X)".
+ return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP));
+ } else {
+ // If this identifier isn't 'defined' or one of the special
+ // preprocessor keywords and it wasn't macro expanded, it turns
+ // into a simple 0, unless it is the C++ keyword "true", in which case it
+ // turns into "1".
if (ValueLive)
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
Result.Val = II->getTokenID() == tok::kw_true;
@@ -99,57 +158,6 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.LexNonComment(PeekTok);
return false;
}
-
- // Handle "defined X" and "defined(X)".
- Result.setBegin(PeekTok.getLocation());
-
- // Get the next token, don't expand it.
- PP.LexUnexpandedToken(PeekTok);
-
- // Two options, it can either be a pp-identifier or a (.
- SourceLocation LParenLoc;
- if (PeekTok.is(tok::l_paren)) {
- // Found a paren, remember we saw it and skip it.
- LParenLoc = PeekTok.getLocation();
- PP.LexUnexpandedToken(PeekTok);
- }
-
- // If we don't have a pp-identifier now, this is an error.
- if ((II = PeekTok.getIdentifierInfo()) == 0) {
- PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
- return true;
- }
-
- // Otherwise, we got an identifier, is it defined to something?
- Result.Val = II->hasMacroDefinition();
- Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
-
- // If there is a macro, mark it used.
- if (Result.Val != 0 && ValueLive) {
- MacroInfo *Macro = PP.getMacroInfo(II);
- Macro->setIsUsed(true);
- }
-
- // Consume identifier.
- Result.setEnd(PeekTok.getLocation());
- PP.LexNonComment(PeekTok);
-
- // If we are in parens, ensure we have a trailing ).
- if (LParenLoc.isValid()) {
- if (PeekTok.isNot(tok::r_paren)) {
- PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen);
- PP.Diag(LParenLoc, diag::note_matching) << "(";
- return true;
- }
- // Consume the ).
- Result.setEnd(PeekTok.getLocation());
- PP.LexNonComment(PeekTok);
- }
-
- // Success, remember that we saw defined(X).
- DT.State = DefinedTracker::DefinedMacro;
- DT.TheMacro = II;
- return false;
}
switch (PeekTok.getKind()) {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 7ddf215020d0..699b701ea870 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -64,8 +64,10 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
// Clang Extensions.
- Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
- Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+ Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
+ Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
}
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
@@ -503,6 +505,117 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
}
}
+/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
+/// or '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP,
+ const DirectoryLookup *LookupFrom) {
+ SourceLocation LParenLoc;
+
+ // Get '('.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a '('.
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
+ return false;
+ }
+
+ // Save '(' location for possible missing ')' message.
+ LParenLoc = Tok.getLocation();
+
+ // Get the file name.
+ PP.getCurrentLexer()->LexIncludeFilename(Tok);
+
+ // Reserve a buffer to get the spelling.
+ llvm::SmallVector<char, 128> FilenameBuffer;
+ const char *FilenameStart, *FilenameEnd;
+
+ switch (Tok.getKind()) {
+ case tok::eom:
+ // If the token kind is EOM, the error has already been diagnosed.
+ return false;
+
+ case tok::angle_string_literal:
+ case tok::string_literal: {
+ FilenameBuffer.resize(Tok.getLength());
+ FilenameStart = &FilenameBuffer[0];
+ unsigned Len = PP.getSpelling(Tok, FilenameStart);
+ FilenameEnd = FilenameStart+Len;
+ break;
+ }
+
+ case tok::less:
+ // This could be a <foo/bar.h> file coming from a macro expansion. In this
+ // case, glue the tokens together into FilenameBuffer and interpret those.
+ FilenameBuffer.push_back('<');
+ if (PP.ConcatenateIncludeName(FilenameBuffer))
+ return false; // Found <eom> but no ">"? Diagnostic already emitted.
+ FilenameStart = FilenameBuffer.data();
+ FilenameEnd = FilenameStart + FilenameBuffer.size();
+ break;
+ default:
+ PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);
+ return false;
+ }
+
+ bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(),
+ FilenameStart, FilenameEnd);
+ // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+ // error.
+ if (FilenameStart == 0) {
+ return false;
+ }
+
+ // Search include directories.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = PP.LookupFile(FilenameStart, FilenameEnd,
+ isAngled, LookupFrom, CurDir);
+
+ // Get the result value. Result = true means the file exists.
+ Result = File != 0;
+
+ // Get ')'.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a trailing ).
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return false;
+ }
+
+ return true;
+}
+
+/// EvaluateHasInclude - Process a '__has_include("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasInclude(bool &Result, Token &Tok, IdentifierInfo *II,
+ Preprocessor &PP) {
+ return(EvaluateHasIncludeCommon(Result, Tok, II, PP, NULL));
+}
+
+/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeNext(bool &Result, Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP) {
+ // __has_include_next is like __has_include, except that we start
+ // searching after the current found directory. If we can't do this,
+ // issue a diagnostic.
+ const DirectoryLookup *Lookup = PP.GetCurDirLookup();
+ if (PP.isInPrimaryFile()) {
+ Lookup = 0;
+ PP.Diag(Tok, diag::pp_include_next_in_primary);
+ } else if (Lookup == 0) {
+ PP.Diag(Tok, diag::pp_include_next_absolute_path);
+ } else {
+ // Start looking up in the next directory.
+ ++Lookup;
+ }
+
+ return(EvaluateHasIncludeCommon(Result, Tok, II, PP, Lookup));
+}
/// 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'.
@@ -671,6 +784,20 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
sprintf(TmpBuffer, "%d", (int)Value);
Tok.setKind(tok::numeric_constant);
CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation());
+ } else if (II == Ident__has_include ||
+ II == Ident__has_include_next) {
+ // The argument to these two builtins should be a parenthesized
+ // file name string literal using angle brackets (<>) or
+ // double-quotes ("").
+ bool Value = false;
+ bool IsValid;
+ if (II == Ident__has_include)
+ IsValid = EvaluateHasInclude(Value, Tok, II, *this);
+ else
+ IsValid = EvaluateHasIncludeNext(Value, Tok, II, *this);
+ 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/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 224a31cd5a5e..344ce9e90e55 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/AttributeList.h"
#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
@@ -52,94 +53,58 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
AttrName = AttrName.substr(2, AttrName.size() - 4);
// FIXME: Hand generating this is neither smart nor efficient.
- const char *Str = AttrName.data();
- switch (AttrName.size()) {
- case 4:
- if (!memcmp(Str, "weak", 4)) return AT_weak;
- if (!memcmp(Str, "pure", 4)) return AT_pure;
- if (!memcmp(Str, "mode", 4)) return AT_mode;
- if (!memcmp(Str, "used", 4)) return AT_used;
- break;
- case 5:
- if (!memcmp(Str, "alias", 5)) return AT_alias;
- if (!memcmp(Str, "const", 5)) return AT_const;
- break;
- case 6:
- if (!memcmp(Str, "packed", 6)) return AT_packed;
- if (!memcmp(Str, "malloc", 6)) return AT_malloc;
- if (!memcmp(Str, "format", 6)) return AT_format;
- if (!memcmp(Str, "unused", 6)) return AT_unused;
- if (!memcmp(Str, "blocks", 6)) return AT_blocks;
- break;
- case 7:
- if (!memcmp(Str, "aligned", 7)) return AT_aligned;
- if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
- if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
- if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
- if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
- if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
- if (!memcmp(Str, "regparm", 7)) return AT_regparm;
- if (!memcmp(Str, "section", 7)) return AT_section;
- if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
- break;
- case 8:
- if (!memcmp(Str, "annotate", 8)) return AT_annotate;
- if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
- if (!memcmp(Str, "noinline", 8)) return AT_noinline;
- if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
- if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
- if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
- if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
- break;
- case 9:
- if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
- if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
- if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
- break;
- case 10:
- if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
- if (!memcmp(Str, "visibility", 10)) return AT_visibility;
- if (!memcmp(Str, "destructor", 10)) return AT_destructor;
- if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
- if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline;
- break;
- case 11:
- if (!memcmp(Str, "weak_import", 11)) return AT_weak_import;
- if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
- if (!memcmp(Str, "constructor", 11)) return AT_constructor;
- if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
- break;
- case 12:
- if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
- break;
- case 13:
- if (!memcmp(Str, "address_space", 13)) return AT_address_space;
- if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
- if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute;
- break;
- case 14:
- if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
- break;
- case 15:
- if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
- break;
- case 17:
- if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
- if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn;
- break;
- case 18:
- if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
- break;
- case 19:
- if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
- if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
- break;
- case 20:
- if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
- case 22:
- if (!memcmp(Str, "no_instrument_function", 22))
- return AT_no_instrument_function;
- break;
- }
- return UnknownAttribute;
+ return llvm::StringSwitch<AttributeList::Kind>(AttrName)
+ .Case("weak", AT_weak)
+ .Case("pure", AT_pure)
+ .Case("mode", AT_mode)
+ .Case("used", AT_used)
+ .Case("alias", AT_alias)
+ .Case("const", AT_const)
+ .Case("packed", AT_packed)
+ .Case("malloc", AT_malloc)
+ .Case("format", AT_format)
+ .Case("unused", AT_unused)
+ .Case("blocks", AT_blocks)
+ .Case("aligned", AT_aligned)
+ .Case("cleanup", AT_cleanup)
+ .Case("nodebug", AT_nodebug)
+ .Case("nonnull", AT_nonnull)
+ .Case("nothrow", AT_nothrow)
+ .Case("objc_gc", AT_objc_gc)
+ .Case("regparm", AT_regparm)
+ .Case("section", AT_section)
+ .Case("stdcall", AT_stdcall)
+ .Case("annotate", AT_annotate)
+ .Case("noreturn", AT_noreturn)
+ .Case("noinline", AT_noinline)
+ .Case("fastcall", AT_fastcall)
+ .Case("iboutlet", AT_IBOutlet)
+ .Case("sentinel", AT_sentinel)
+ .Case("NSObject", AT_nsobject)
+ .Case("dllimport", AT_dllimport)
+ .Case("dllexport", AT_dllexport)
+ .Case("may_alias", IgnoredAttribute) // FIXME: TBAA
+ .Case("deprecated", AT_deprecated)
+ .Case("visibility", AT_visibility)
+ .Case("destructor", AT_destructor)
+ .Case("format_arg", AT_format_arg)
+ .Case("gnu_inline", AT_gnu_inline)
+ .Case("weak_import", AT_weak_import)
+ .Case("vector_size", AT_vector_size)
+ .Case("constructor", AT_constructor)
+ .Case("unavailable", AT_unavailable)
+ .Case("overloadable", AT_overloadable)
+ .Case("address_space", AT_address_space)
+ .Case("always_inline", AT_always_inline)
+ .Case("vec_type_hint", IgnoredAttribute)
+ .Case("objc_exception", AT_objc_exception)
+ .Case("ext_vector_type", AT_ext_vector_type)
+ .Case("transparent_union", AT_transparent_union)
+ .Case("analyzer_noreturn", AT_analyzer_noreturn)
+ .Case("warn_unused_result", AT_warn_unused_result)
+ .Case("ns_returns_retained", AT_ns_returns_retained)
+ .Case("cf_returns_retained", AT_cf_returns_retained)
+ .Case("reqd_work_group_size", AT_reqd_wg_size)
+ .Case("no_instrument_function", AT_no_instrument_function)
+ .Default(UnknownAttribute);
}
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index b8422aad5a84..3436900027e4 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -446,3 +446,28 @@ bool DeclSpec::isMissingDeclaratorOk() {
|| tst == TST_enum
) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
}
+
+void UnqualifiedId::clear() {
+ if (Kind == IK_TemplateId)
+ TemplateId->Destroy();
+
+ Kind = IK_Identifier;
+ Identifier = 0;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]) {
+ Kind = IK_OperatorFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = OperatorLoc;
+ OperatorFunctionId.Operator = Op;
+ for (unsigned I = 0; I != 3; ++I) {
+ OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+
+ if (SymbolLocations[I].isValid())
+ EndLocation = SymbolLocations[I];
+ }
+}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 71b22cad6f62..1e7d397fdf37 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -161,9 +161,8 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
TemplateNameKind
MinimalAction::isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringScope,
TemplateTy &TemplateDecl) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b56c33170cbf..e905553fd818 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -336,10 +336,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
/// If RequireSemi is false, this does not check for a ';' at the end of the
/// declaration.
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi) {
+ SourceLocation &DeclEnd) {
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -347,32 +346,109 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
if (Tok.is(tok::semi)) {
ConsumeToken();
DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
- ParseDeclarator(DeclaratorInfo);
+ DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false,
+ &DeclEnd);
+ return DG;
+}
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+/// ParseDeclGroup - Having concluded that this is either a function
+/// definition or a group of object declarations, actually parse the
+/// result.
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
+ unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd) {
+ // Parse the first declarator.
+ ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+ ParseDeclarator(D);
+
+ // Bail out if the first declarator didn't seem well-formed.
+ if (!D.hasName() && !D.mayOmitIdentifier()) {
+ // Skip until ; or }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
+
+ if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
+ if (isDeclarationAfterDeclarator()) {
+ // Fall though. We have to check this first, though, because
+ // __attribute__ might be the start of a function definition in
+ // (extended) K&R C.
+ } else if (isStartOfFunctionDefinition()) {
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
+
+ // Recover by treating the 'typedef' as spurious.
+ DS.ClearStorageClassSpecs();
+ }
- DeclEnd = Tok.getLocation();
+ DeclPtrTy TheDecl = ParseFunctionDefinition(D);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ } else {
+ Diag(Tok, diag::err_expected_fn_body);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
+ }
+ }
- // If the client wants to check what comes after the declaration, just return
- // immediately without checking anything!
- if (!RequireSemi) return DG;
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
+ DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(FirstDecl);
+ if (FirstDecl.get())
+ DeclsInGroup.push_back(FirstDecl);
- if (Tok.is(tok::semi)) {
+ // If we don't have a comma, it is either the end of the list (a ';') or an
+ // error, bail out.
+ while (Tok.is(tok::comma)) {
+ // Consume the comma.
ConsumeToken();
- return DG;
+
+ // Parse the next declarator.
+ D.clear();
+
+ // Accept attributes in an init-declarator. In the first declarator in a
+ // declaration, these would be part of the declspec. In subsequent
+ // declarators, they become part of the declarator itself, so that they
+ // don't apply to declarators after *this* one. Examples:
+ // short __attribute__((common)) var; -> declspec
+ // short var __attribute__((common)); -> declarator
+ // short x, __attribute__((common)) var; -> declarator
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ D.AddAttributes(AttrList, Loc);
+ }
+
+ ParseDeclarator(D);
+
+ DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(ThisDecl);
+ if (ThisDecl.get())
+ DeclsInGroup.push_back(ThisDecl);
}
- Diag(Tok, diag::err_expected_semi_declaration);
- // Skip to end of block or statement
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return DG;
+ if (DeclEnd)
+ *DeclEnd = Tok.getLocation();
+
+ if (Context != Declarator::ForContext &&
+ ExpectAndConsume(tok::semi,
+ Context == Declarator::FileContext
+ ? diag::err_invalid_token_after_toplevel_declarator
+ : diag::err_expected_semi_declaration)) {
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+
+ return Actions.FinalizeDeclaratorGroup(CurScope, DS,
+ DeclsInGroup.data(),
+ DeclsInGroup.size());
}
/// \brief Parse 'declaration' after parsing 'declaration-specifiers
@@ -498,63 +574,6 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
return ThisDecl;
}
-/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
-/// parsing 'declaration-specifiers declarator'. This method is split out this
-/// way to handle the ambiguity between top-level function-definitions and
-/// declarations.
-///
-/// init-declarator-list: [C99 6.7]
-/// init-declarator
-/// init-declarator-list ',' init-declarator
-///
-/// According to the standard grammar, =default and =delete are function
-/// definitions, but that definitely doesn't fit with the parser here.
-///
-Parser::DeclGroupPtrTy Parser::
-ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
- // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
- // that we parse together here.
- llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
-
- // At this point, we know that it is not a function definition. Parse the
- // rest of the init-declarator-list.
- while (1) {
- DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
- if (ThisDecl.get())
- DeclsInGroup.push_back(ThisDecl);
-
- // If we don't have a comma, it is either the end of the list (a ';') or an
- // error, bail out.
- if (Tok.isNot(tok::comma))
- break;
-
- // Consume the comma.
- ConsumeToken();
-
- // Parse the next declarator.
- D.clear();
-
- // Accept attributes in an init-declarator. In the first declarator in a
- // declaration, these would be part of the declspec. In subsequent
- // declarators, they become part of the declarator itself, so that they
- // don't apply to declarators after *this* one. Examples:
- // short __attribute__((common)) var; -> declspec
- // short var __attribute__((common)); -> declarator
- // short x, __attribute__((common)) var; -> declarator
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
-
- ParseDeclarator(D);
- }
-
- return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(),
- DeclsInGroup.data(),
- DeclsInGroup.size());
-}
-
/// ParseSpecifierQualifierList
/// specifier-qualifier-list:
/// type-specifier specifier-qualifier-list[opt]
@@ -1468,8 +1487,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
///
void Parser::
-ParseStructDeclaration(DeclSpec &DS,
- llvm::SmallVectorImpl<FieldDeclarator> &Fields) {
+ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
if (Tok.is(tok::kw___extension__)) {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
@@ -1489,9 +1507,17 @@ ParseStructDeclaration(DeclSpec &DS,
}
// Read struct-declarators until we find the semicolon.
- Fields.push_back(FieldDeclarator(DS));
+ bool FirstDeclarator = true;
while (1) {
- FieldDeclarator &DeclaratorInfo = Fields.back();
+ ParsingDeclRAIIObject PD(*this);
+ FieldDeclarator DeclaratorInfo(DS);
+
+ // Attributes are only allowed here on successive declarators.
+ if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ DeclaratorInfo.D.AddAttributes(AttrList, Loc);
+ }
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
@@ -1514,6 +1540,10 @@ ParseStructDeclaration(DeclSpec &DS,
DeclaratorInfo.D.AddAttributes(AttrList, Loc);
}
+ // We're done with this declarator; invoke the callback.
+ DeclPtrTy D = Fields.invoke(DeclaratorInfo);
+ PD.complete(D);
+
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
@@ -1522,15 +1552,7 @@ ParseStructDeclaration(DeclSpec &DS,
// Consume the comma.
ConsumeToken();
- // Parse the next declarator.
- Fields.push_back(FieldDeclarator(DS));
-
- // Attributes are only allowed on the second declarator.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- Fields.back().D.AddAttributes(AttrList, Loc);
- }
+ FirstDeclarator = false;
}
}
@@ -1562,7 +1584,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
<< DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
// While we still have something to read, read the declarations in the struct.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@@ -1578,28 +1599,28 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// Parse all the comma separated declarators.
DeclSpec DS;
- FieldDeclarators.clear();
+
if (!Tok.is(tok::at)) {
- ParseStructDeclaration(DS, FieldDeclarators);
-
- // Convert them all to fields.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- DeclPtrTy Field;
- // Install the declarator into the current TagDecl.
- if (FD.D.getExtension()) {
- // Silences extension warnings
- ExtensionRAIIObject O(Diags);
- Field = Actions.ActOnField(CurScope, TagDecl,
- DS.getSourceRange().getBegin(),
- FD.D, FD.BitfieldSize);
- } else {
- Field = Actions.ActOnField(CurScope, TagDecl,
- DS.getSourceRange().getBegin(),
- FD.D, FD.BitfieldSize);
+ struct CFieldCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy TagDecl;
+ llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
+
+ CFieldCallback(Parser &P, DeclPtrTy TagDecl,
+ llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
+ P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
+
+ virtual DeclPtrTy invoke(FieldDeclarator &FD) {
+ // Install the declarator into the current TagDecl.
+ DeclPtrTy Field = P.Actions.ActOnField(P.CurScope, TagDecl,
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ FD.D, FD.BitfieldSize);
+ FieldDecls.push_back(Field);
+ return Field;
}
- FieldDecls.push_back(Field);
- }
+ } Callback(*this, TagDecl, FieldDecls);
+
+ ParseStructDeclaration(DS, Callback);
} else { // Handle @defs
ConsumeToken();
if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
@@ -2107,7 +2128,6 @@ void Parser::ParseDeclarator(Declarator &D) {
/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
void Parser::ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser) {
-
if (Diags.hasAllExtensionsSilenced())
D.setExtension();
// C++ member pointers start with a '::' or a nested-name.
@@ -2270,97 +2290,47 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
void Parser::ParseDirectDeclarator(Declarator &D) {
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
- if (getLang().CPlusPlus) {
- if (D.mayHaveIdentifier()) {
- // ParseDeclaratorInternal might already have parsed the scope.
- bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
- true);
- if (afterCXXScope) {
- // Change the declaration context for name lookup, until this function
- // is exited (and the declarator has been parsed).
- DeclScopeObj.EnterDeclaratorScope();
- }
-
- if (Tok.is(tok::identifier)) {
- assert(Tok.getIdentifierInfo() && "Not an identifier?");
-
- // If this identifier is the name of the current class, it's a
- // constructor name.
- if (!D.getDeclSpec().hasTypeSpecifier() &&
- Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) {
- CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
- D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope, SS),
- Tok.getLocation());
- // This is a normal identifier.
- } else
- D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeToken();
- goto PastIdentifier;
- } else if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-
- D.setTemplateId(TemplateId);
- ConsumeToken();
- goto PastIdentifier;
- } else if (Tok.is(tok::kw_operator)) {
- SourceLocation OperatorLoc = Tok.getLocation();
- SourceLocation EndLoc;
-
- // First try the name of an overloaded operator
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) {
- D.setOverloadedOperator(Op, OperatorLoc, EndLoc);
- } else {
- // This must be a conversion function (C++ [class.conv.fct]).
- if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc))
- D.setConversionFunction(ConvType, OperatorLoc, EndLoc);
- else {
- D.SetIdentifier(0, Tok.getLocation());
- }
- }
- goto PastIdentifier;
- } else if (Tok.is(tok::tilde)) {
- // This should be a C++ destructor.
- SourceLocation TildeLoc = ConsumeToken();
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
- // FIXME: Inaccurate.
- SourceLocation NameLoc = Tok.getLocation();
- SourceLocation EndLoc;
- CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
- TypeResult Type = ParseClassName(EndLoc, SS, true);
- if (Type.isInvalid())
- D.SetIdentifier(0, TildeLoc);
- else
- D.setDestructor(Type.get(), TildeLoc, NameLoc);
- } else {
- Diag(Tok, diag::err_destructor_class_name);
- D.SetIdentifier(0, TildeLoc);
- }
- goto PastIdentifier;
- }
-
- // If we reached this point, token is not identifier and not '~'.
-
- if (afterCXXScope) {
- Diag(Tok, diag::err_expected_unqualified_id);
+ if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
+ // ParseDeclaratorInternal might already have parsed the scope.
+ bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+ true);
+ if (afterCXXScope) {
+ // Change the declaration context for name lookup, until this function
+ // is exited (and the declarator has been parsed).
+ DeclScopeObj.EnterDeclaratorScope();
+ }
+
+ if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+ Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+ // We found something that indicates the start of an unqualified-id.
+ // Parse that unqualified-id.
+ if (ParseUnqualifiedId(D.getCXXScopeSpec(),
+ /*EnteringContext=*/true,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(),
+ /*ObjectType=*/0,
+ D.getName())) {
D.SetIdentifier(0, Tok.getLocation());
D.setInvalidType(true);
- goto PastIdentifier;
+ } else {
+ // Parsed the unqualified-id; update range information and move along.
+ if (D.getSourceRange().getBegin().isInvalid())
+ D.SetRangeBegin(D.getName().getSourceRange().getBegin());
+ D.SetRangeEnd(D.getName().getSourceRange().getEnd());
}
+ goto PastIdentifier;
}
- }
-
- // If we reached this point, we are either in C/ObjC or the token didn't
- // satisfy any of the C++-specific checks.
- if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
+ } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
assert(!getLang().CPlusPlus &&
"There's a C++-specific check for tok::identifier above");
assert(Tok.getIdentifierInfo() && "Not an identifier?");
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
- } else if (Tok.is(tok::l_paren)) {
+ goto PastIdentifier;
+ }
+
+ if (Tok.is(tok::l_paren)) {
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
// Example: 'char (*X)' or 'int (*XX)(void)'
@@ -2374,7 +2344,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
Diag(Tok, diag::err_expected_member_name_or_semi)
<< D.getDeclSpec().getSourceRange();
else if (getLang().CPlusPlus)
- Diag(Tok, diag::err_expected_unqualified_id);
+ Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
else
Diag(Tok, diag::err_expected_ident_lparen);
D.SetIdentifier(0, Tok.getLocation());
@@ -2623,6 +2593,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
SourceLocation DSStart = Tok.getLocation();
// Parse the declaration-specifiers.
+ // Just use the ParsingDeclaration "scope" of the declarator.
DeclSpec DS;
// If the caller parsed attributes for the first argument, add them now.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index d381e3e97472..91f86864f81f 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -323,6 +323,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
+ // FIXME: what about conversion functions?
} else if (Tok.is(tok::identifier)) {
// Parse identifier.
TargetName = Tok.getIdentifierInfo();
@@ -589,6 +590,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
+ TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
// Parse the (optional) class name or simple-template-id.
IdentifierInfo *Name = 0;
SourceLocation NameLoc;
@@ -596,6 +599,56 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ // The name was supposed to refer to a template, but didn't.
+ // Eat the template argument list and try to continue parsing this as
+ // a class (or template thereof).
+ TemplateArgList TemplateArgs;
+ TemplateArgIsTypeList TemplateArgIsType;
+ TemplateArgLocationList TemplateArgLocations;
+ SourceLocation LAngleLoc, RAngleLoc;
+ if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
+ true, LAngleLoc,
+ TemplateArgs, TemplateArgIsType,
+ TemplateArgLocations, RAngleLoc)) {
+ // We couldn't parse the template argument list at all, so don't
+ // try to give any location information for the list.
+ LAngleLoc = RAngleLoc = SourceLocation();
+ }
+
+ Diag(NameLoc, diag::err_explicit_spec_non_template)
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << (TagType == DeclSpec::TST_class? 0
+ : TagType == DeclSpec::TST_struct? 1
+ : 2)
+ << Name
+ << SourceRange(LAngleLoc, RAngleLoc);
+
+ // Strip off the last template parameter list if it was empty, since
+ // we've removed its template argument list.
+ if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+ if (TemplateParams && TemplateParams->size() > 1) {
+ TemplateParams->pop_back();
+ } else {
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ }
+ } else if (TemplateInfo.Kind
+ == ParsedTemplateInfo::ExplicitInstantiation) {
+ // Pretend this is just a forward declaration.
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
+ = SourceLocation();
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+ = SourceLocation();
+ }
+
+
+ }
} else if (Tok.is(tok::annot_template_id)) {
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
NameLoc = ConsumeToken();
@@ -660,7 +713,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Create the tag portion of the class or class template.
Action::DeclResult TagOrTempResult = true; // invalid
Action::TypeResult TypeResult = true; // invalid
- TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
// FIXME: When TUK == TUK_Reference and we have a template-id, we need
// to turn that template-id into a type.
@@ -1047,7 +1099,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
Action::MultiTemplateParamsArg TemplateParams(Actions,
@@ -1060,7 +1112,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return;
}
- Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+ ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
if (Tok.isNot(tok::colon)) {
// Parse the first declarator.
@@ -1179,6 +1231,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
}
+ DeclaratorInfo.complete(ThisDecl);
+
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 8be89a891680..95a0e989471e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -340,7 +340,18 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
// Eat the colon.
ColonLoc = ConsumeToken();
}
-
+
+ if ((OpToken.is(tok::periodstar) || OpToken.is(tok::arrowstar))
+ && Tok.is(tok::identifier)) {
+ CXXScopeSpec SS;
+ if (Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), CurScope, &SS)) {
+ const char *Opc = OpToken.is(tok::periodstar) ? "'.*'" : "'->*'";
+ Diag(OpToken, diag::err_pointer_to_member_type) << Opc;
+ return ExprError();
+ }
+
+ }
// Parse another leaf here for the RHS of the operator.
// ParseCastExpression works here because all RHS expressions in C have it
// as a prefix, at least. However, in C++, an assignment-expression could
@@ -612,36 +623,39 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
}
- // Support 'Class.property' notation.
- // We don't use isTokObjCMessageIdentifierReceiver(), since it allows
- // 'super' (which is inappropriate here).
- if (getLang().ObjC1 &&
- Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope) &&
- NextToken().is(tok::period)) {
- IdentifierInfo &ReceiverName = *Tok.getIdentifierInfo();
- SourceLocation IdentLoc = ConsumeToken();
+ // Consume the identifier so that we can see if it is followed by a '(' or
+ // '.'.
+ IdentifierInfo &II = *Tok.getIdentifierInfo();
+ SourceLocation ILoc = ConsumeToken();
+
+ // Support 'Class.property' notation. We don't use
+ // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
+ // inappropriate here).
+ if (getLang().ObjC1 && Tok.is(tok::period) &&
+ Actions.getTypeName(II, ILoc, CurScope)) {
SourceLocation DotLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected_property_name);
return ExprError();
}
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
SourceLocation PropertyLoc = ConsumeToken();
-
- Res = Actions.ActOnClassPropertyRefExpr(ReceiverName, PropertyName,
- IdentLoc, PropertyLoc);
+
+ Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
+ ILoc, PropertyLoc);
// These can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(move(Res));
}
- // Consume the identifier so that we can see if it is followed by a '('.
+
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
- IdentifierInfo &II = *Tok.getIdentifierInfo();
- SourceLocation L = ConsumeToken();
- Res = Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren));
+ UnqualifiedId Name;
+ CXXScopeSpec ScopeSpec;
+ Name.setIdentifier(&II, ILoc);
+ Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name,
+ Tok.is(tok::l_paren), false);
// These can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(move(Res));
}
@@ -954,110 +968,20 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ConsumeToken();
}
- if (Tok.is(tok::identifier)) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
- OpKind, Tok.getLocation(),
- *Tok.getIdentifierInfo(),
- ObjCImpDecl, &SS);
- ConsumeToken();
- } else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
- // We have a C++ pseudo-destructor or a destructor call, e.g., t.~T()
-
- // Consume the tilde.
- ConsumeToken();
-
- if (!Tok.is(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return ExprError();
- }
-
- if (NextToken().is(tok::less)) {
- // class-name:
- // ~ simple-template-id
- TemplateTy Template
- = Actions.ActOnDependentTemplateName(SourceLocation(),
- *Tok.getIdentifierInfo(),
- Tok.getLocation(),
- SS,
- ObjectType);
- if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS,
- SourceLocation(), true))
- return ExprError();
-
- assert(Tok.is(tok::annot_typename) &&
- "AnnotateTemplateIdToken didn't work?");
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getAnnotationRange(),
- Tok.getAnnotationValue(),
- SS,
- NextToken().is(tok::l_paren));
- } else {
- // class-name:
- // ~ identifier
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getLocation(),
- Tok.getIdentifierInfo(),
- SS,
- NextToken().is(tok::l_paren));
- }
-
- // Consume the identifier or template-id token.
- ConsumeToken();
- } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
- // We have a reference to a member operator, e.g., t.operator int or
- // t.operator+.
- SourceLocation OperatorLoc = Tok.getLocation();
-
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
- move(LHS), OpLoc,
- OpKind,
- OperatorLoc,
- Op, &SS);
- // TryParseOperatorFunctionId already consumed our token, so
- // don't bother
- } else if (TypeTy *ConvType = ParseConversionFunctionId()) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnConversionOperatorReferenceExpr(CurScope,
- move(LHS), OpLoc,
- OpKind,
- OperatorLoc,
- ConvType, &SS);
- } else {
- // Don't emit a diagnostic; ParseConversionFunctionId does it for us
- return ExprError();
- }
- } else if (getLang().CPlusPlus && Tok.is(tok::annot_template_id)) {
- // We have a reference to a member template along with explicitly-
- // specified template arguments, e.g., t.f<int>.
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- if (!LHS.isInvalid()) {
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
- TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
- TemplateId->NumArgs);
-
- LHS = Actions.ActOnMemberTemplateIdReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind, SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc);
- }
- ConsumeToken();
- } else {
- Diag(Tok, diag::err_expected_ident);
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/false,
+ ObjectType,
+ Name))
return ExprError();
- }
+
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
+ SS, Name, ObjCImpDecl,
+ Tok.is(tok::l_paren));
+
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index fa651569f8e1..a7ca0c54dbe6 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,8 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/ErrorHandling.h"
+
using namespace clang;
/// \brief Parse global scope or nested-name-specifier if present.
@@ -107,31 +109,58 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
break;
SourceLocation TemplateKWLoc = ConsumeToken();
-
- if (Tok.isNot(tok::identifier)) {
+
+ UnqualifiedId TemplateName;
+ if (Tok.is(tok::identifier)) {
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+
+ // If the next token is not '<', we may have a stray 'template' keyword.
+ // Complain and suggest removing the template keyword, but otherwise
+ // allow parsing to continue.
+ if (NextToken().isNot(tok::less)) {
+ Diag(NextToken().getLocation(),
+ diag::err_less_after_template_name_in_nested_name_spec)
+ << Tok.getIdentifierInfo()->getName()
+ << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc));
+ break;
+ }
+
+ // Consume the identifier.
+ ConsumeToken();
+ } else if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ TemplateName))
+ break;
+
+ if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) {
+ Diag(TemplateName.getSourceRange().getBegin(),
+ diag::err_id_after_template_in_nested_name_spec)
+ << TemplateName.getSourceRange();
+ break;
+ } else if (Tok.isNot(tok::less)) {
+ std::string OperatorName = "operator ";
+ OperatorName += getOperatorSpelling(
+ TemplateName.OperatorFunctionId.Operator);
+ Diag(Tok.getLocation(),
+ diag::err_less_after_template_name_in_nested_name_spec)
+ << OperatorName
+ << TemplateName.getSourceRange();
+ break;
+ }
+ } else {
Diag(Tok.getLocation(),
diag::err_id_after_template_in_nested_name_spec)
<< SourceRange(TemplateKWLoc);
break;
}
- if (NextToken().isNot(tok::less)) {
- Diag(NextToken().getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << Tok.getIdentifierInfo()->getName()
- << SourceRange(TemplateKWLoc, Tok.getLocation());
- break;
- }
-
TemplateTy Template
- = Actions.ActOnDependentTemplateName(TemplateKWLoc,
- *Tok.getIdentifierInfo(),
- Tok.getLocation(), SS,
+ = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
ObjectType);
if (!Template)
break;
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
- &SS, TemplateKWLoc, false))
+ &SS, TemplateName, TemplateKWLoc, false))
break;
continue;
@@ -218,9 +247,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// type-name '<'
if (Next.is(tok::less)) {
TemplateTy Template;
- if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
- Tok.getLocation(),
- &SS,
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(&II, Tok.getLocation());
+ if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS,
+ TemplateName,
ObjectType,
EnteringContext,
Template)) {
@@ -230,8 +260,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// because some clients (e.g., the parsing of class template
// specializations) still want to see the original template-id
// token.
- if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
- false))
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
+ SourceLocation(), false))
break;
continue;
}
@@ -251,25 +282,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
/// unqualified-id
/// qualified-id
///
-/// unqualified-id:
-/// identifier
-/// operator-function-id
-/// conversion-function-id [TODO]
-/// '~' class-name [TODO]
-/// template-id
-///
/// qualified-id:
/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
/// '::' identifier
/// '::' operator-function-id
/// '::' template-id
///
-/// nested-name-specifier:
-/// type-name '::'
-/// namespace-name '::'
-/// nested-name-specifier identifier '::'
-/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
-///
/// NOTE: The standard specifies that, for qualified-id, the parser does not
/// expect:
///
@@ -307,69 +325,19 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
//
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
-
- // unqualified-id:
- // identifier
- // operator-function-id
- // conversion-function-id
- // '~' class-name [TODO]
- // template-id
- //
- switch (Tok.getKind()) {
- default:
- return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
-
- case tok::identifier: {
- // Consume the identifier so that we can see if it is followed by a '('.
- IdentifierInfo &II = *Tok.getIdentifierInfo();
- SourceLocation L = ConsumeToken();
- return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
- &SS, isAddressOfOperand);
- }
-
- case tok::kw_operator: {
- SourceLocation OperatorLoc = Tok.getLocation();
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
- return Actions.ActOnCXXOperatorFunctionIdExpr(
- CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
- isAddressOfOperand);
- if (TypeTy *Type = ParseConversionFunctionId())
- return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
- Tok.is(tok::l_paren), SS,
- isAddressOfOperand);
-
- // We already complained about a bad conversion-function-id,
- // above.
+
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/false,
+ /*AllowConstructorName=*/false,
+ /*ObjectType=*/0,
+ Name))
return ExprError();
- }
-
- case tok::annot_template_id: {
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- assert((TemplateId->Kind == TNK_Function_template ||
- TemplateId->Kind == TNK_Dependent_template_name) &&
- "A template type name is not an ID expression");
-
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
- TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
- TemplateId->NumArgs);
-
- OwningExprResult Result
- = Actions.ActOnTemplateIdExpr(SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc);
- ConsumeToken(); // Consume the template-id token
- return move(Result);
- }
-
- } // switch.
-
- assert(0 && "The switch was supposed to take care everything.");
+
+ return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
+ isAddressOfOperand);
+
}
/// ParseCXXCasts - This handles the various ways to cast expressions to another
@@ -761,6 +729,473 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
return false;
}
+/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// some form.
+///
+/// This routine is invoked when a '<' is encountered after an identifier or
+/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
+/// whether the unqualified-id is actually a template-id. This routine will
+/// then parse the template arguments and form the appropriate template-id to
+/// return to the caller.
+///
+/// \param SS the nested-name-specifier that precedes this template-id, if
+/// we're actually parsing a qualified-id.
+///
+/// \param Name for constructor and destructor names, this is the actual
+/// identifier that may be a template-name.
+///
+/// \param NameLoc the location of the class-name in a constructor or
+/// destructor.
+///
+/// \param EnteringContext whether we're entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Id as input, describes the template-name or operator-function-id
+/// that precedes the '<'. If template arguments were parsed successfully,
+/// will be updated with the template-id.
+///
+/// \returns true if a parse error occurred, false otherwise.
+bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Id) {
+ assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+
+ TemplateTy Template;
+ TemplateNameKind TNK = TNK_Non_template;
+ switch (Id.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
+ Template);
+ break;
+
+ case UnqualifiedId::IK_ConstructorName: {
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Name, NameLoc);
+ TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
+ EnteringContext, Template);
+ break;
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Name, NameLoc);
+ if (ObjectType) {
+ Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ TemplateName, ObjectType);
+ TNK = TNK_Dependent_template_name;
+ if (!Template.get())
+ return true;
+ } else {
+ TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
+ EnteringContext, Template);
+
+ if (TNK == TNK_Non_template && Id.DestructorName == 0) {
+ // The identifier following the destructor did not refer to a template
+ // or to a type. Complain.
+ if (ObjectType)
+ Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << Name;
+ else
+ Diag(NameLoc, diag::err_destructor_class_name);
+ return true;
+ }
+ }
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ if (TNK == TNK_Non_template)
+ return false;
+
+ // Parse the enclosed template argument list.
+ SourceLocation LAngleLoc, RAngleLoc;
+ TemplateArgList TemplateArgs;
+ TemplateArgIsTypeList TemplateArgIsType;
+ TemplateArgLocationList TemplateArgLocations;
+ if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+ &SS, true, LAngleLoc,
+ TemplateArgs,
+ TemplateArgIsType,
+ TemplateArgLocations,
+ RAngleLoc))
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier ||
+ Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) {
+ // Form a parsed representation of the template-id to be stored in the
+ // UnqualifiedId.
+ TemplateIdAnnotation *TemplateId
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = Id.Identifier;
+ TemplateId->Operator = OO_None;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = Id.OperatorFunctionId.Operator;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ }
+
+ TemplateId->Template = Template.getAs<void*>();
+ TemplateId->Kind = TNK;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->RAngleLoc = RAngleLoc;
+ void **Args = TemplateId->getTemplateArgs();
+ bool *ArgIsType = TemplateId->getTemplateArgIsType();
+ SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
+ Arg != ArgEnd; ++Arg) {
+ Args[Arg] = TemplateArgs[Arg];
+ ArgIsType[Arg] = TemplateArgIsType[Arg];
+ ArgLocs[Arg] = TemplateArgLocations[Arg];
+ }
+
+ Id.setTemplateId(TemplateId);
+ return false;
+ }
+
+ // Bundle the template arguments together.
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+ TemplateArgIsType.data(),
+ TemplateArgs.size());
+
+ // Constructor and destructor names.
+ Action::TypeResult Type
+ = Actions.ActOnTemplateIdType(Template, NameLoc,
+ LAngleLoc, TemplateArgsPtr,
+ &TemplateArgLocations[0],
+ RAngleLoc);
+ if (Type.isInvalid())
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
+ else
+ Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+
+ return false;
+}
+
+/// \brief Parse an operator-function-id or conversion-function-id as part
+/// of a C++ unqualified-id.
+///
+/// This routine is responsible only for parsing the operator-function-id or
+/// conversion-function-id; it does not handle template arguments in any way.
+///
+/// \code
+/// operator-function-id: [C++ 13.5]
+/// 'operator' operator
+///
+/// operator: one of
+/// new delete new[] delete[]
+/// + - * / % ^ & | ~
+/// ! = < > += -= *= /= %=
+/// ^= &= |= << >> >>= <<= == !=
+/// <= >= && || ++ -- , ->* ->
+/// () []
+///
+/// conversion-function-id: [C++ 12.3.2]
+/// operator conversion-type-id
+///
+/// conversion-type-id:
+/// type-specifier-seq conversion-declarator[opt]
+///
+/// conversion-declarator:
+/// ptr-operator conversion-declarator[opt]
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result) {
+ assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
+
+ // Consume the 'operator' keyword.
+ SourceLocation KeywordLoc = ConsumeToken();
+
+ // Determine what kind of operator name we have.
+ unsigned SymbolIdx = 0;
+ SourceLocation SymbolLocations[3];
+ OverloadedOperatorKind Op = OO_None;
+ switch (Tok.getKind()) {
+ case tok::kw_new:
+ case tok::kw_delete: {
+ bool isNew = Tok.getKind() == tok::kw_new;
+ // Consume the 'new' or 'delete'.
+ SymbolLocations[SymbolIdx++] = ConsumeToken();
+ if (Tok.is(tok::l_square)) {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = isNew? OO_Array_New : OO_Array_Delete;
+ } else {
+ Op = isNew? OO_New : OO_Delete;
+ }
+ break;
+ }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case tok::Token: \
+ SymbolLocations[SymbolIdx++] = ConsumeToken(); \
+ Op = OO_##Name; \
+ break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+
+ case tok::l_paren: {
+ // Consume the '('.
+ SourceLocation LParenLoc = ConsumeParen();
+ // Consume the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
+ LParenLoc);
+ if (RParenLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LParenLoc;
+ SymbolLocations[SymbolIdx++] = RParenLoc;
+ Op = OO_Call;
+ break;
+ }
+
+ case tok::l_square: {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = OO_Subscript;
+ break;
+ }
+
+ case tok::code_completion: {
+ // Code completion for the operator name.
+ Actions.CodeCompleteOperatorName(CurScope);
+
+ // Consume the operator token.
+ ConsumeToken();
+
+ // Don't try to parse any further.
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ if (Op != OO_None) {
+ // We have parsed an operator-function-id.
+ Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
+ return false;
+ }
+
+ // Parse a conversion-function-id.
+ //
+ // conversion-function-id: [C++ 12.3.2]
+ // operator conversion-type-id
+ //
+ // conversion-type-id:
+ // type-specifier-seq conversion-declarator[opt]
+ //
+ // conversion-declarator:
+ // ptr-operator conversion-declarator[opt]
+
+ // Parse the type-specifier-seq.
+ DeclSpec DS;
+ if (ParseCXXTypeSpecifierSeq(DS))
+ return true;
+
+ // Parse the conversion-declarator, which is merely a sequence of
+ // ptr-operators.
+ Declarator D(DS, Declarator::TypeNameContext);
+ ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
+
+ // Finish up the type.
+ Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
+ if (Ty.isInvalid())
+ return true;
+
+ // Note that this is a conversion-function-id.
+ Result.setConversionFunctionId(KeywordLoc, Ty.get(),
+ D.getSourceRange().getEnd());
+ return false;
+}
+
+/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// name of an entity.
+///
+/// \code
+/// unqualified-id: [C++ expr.prim.general]
+/// identifier
+/// operator-function-id
+/// conversion-function-id
+/// [C++0x] literal-operator-id [TODO]
+/// ~ class-name
+/// template-id
+///
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param AllowDestructorName whether we allow parsing of a destructor name.
+///
+/// \param AllowConstructorName whether we allow parsing a constructor name.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result) {
+ // unqualified-id:
+ // identifier
+ // template-id (when it hasn't already been annotated)
+ if (Tok.is(tok::identifier)) {
+ // Consume the identifier.
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (AllowConstructorName &&
+ Actions.isCurrentClassName(*Id, CurScope, &SS)) {
+ // We have parsed a constructor name.
+ Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
+ &SS, false),
+ IdLoc, IdLoc);
+ } else {
+ // We have parsed an identifier.
+ Result.setIdentifier(Id, IdLoc);
+ }
+
+ // If the next token is a '<', we may have a template.
+ if (Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
+ ObjectType, Result);
+
+ return false;
+ }
+
+ // unqualified-id:
+ // template-id (already parsed and annotated)
+ if (Tok.is(tok::annot_template_id)) {
+ // FIXME: Could this be a constructor name???
+
+ // We have already parsed a template-id; consume the annotation token as
+ // our unqualified-id.
+ Result.setTemplateId(
+ static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()));
+ ConsumeToken();
+ return false;
+ }
+
+ // unqualified-id:
+ // operator-function-id
+ // conversion-function-id
+ if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
+ return true;
+
+ // If we have an operator-function-id and the next token is a '<', we may
+ // have a
+ //
+ // template-id:
+ // operator-function-id < template-argument-list[opt] >
+ if (Result.getKind() == UnqualifiedId::IK_OperatorFunctionId &&
+ Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
+ EnteringContext, ObjectType,
+ Result);
+
+ return false;
+ }
+
+ if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+ // C++ [expr.unary.op]p10:
+ // There is an ambiguity in the unary-expression ~X(), where X is a
+ // class-name. The ambiguity is resolved in favor of treating ~ as a
+ // unary complement rather than treating ~X as referring to a destructor.
+
+ // Parse the '~'.
+ SourceLocation TildeLoc = ConsumeToken();
+
+ // Parse the class-name.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_class_name);
+ return true;
+ }
+
+ // Parse the class-name (or template-name in a simple-template-id).
+ IdentifierInfo *ClassName = Tok.getIdentifierInfo();
+ SourceLocation ClassNameLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
+ return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
+ EnteringContext, ObjectType, Result);
+ }
+
+ // Note that this is a destructor name.
+ Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
+ CurScope, &SS);
+ if (!Ty) {
+ if (ObjectType)
+ Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << ClassName;
+ else
+ Diag(ClassNameLoc, diag::err_destructor_class_name);
+ return true;
+ }
+
+ Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
+ return false;
+ }
+
+ Diag(Tok, diag::err_expected_unqualified_id)
+ << getLang().CPlusPlus;
+ return true;
+}
+
/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
/// operator name (C++ [over.oper]). If successful, returns the
/// predefined identifier that corresponds to that overloaded
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 2e0cd6d0d932..b043dd99f304 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -305,51 +305,68 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
if (Tok.is(tok::l_paren))
ParseObjCPropertyAttribute(OCDS);
+ struct ObjCPropertyCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy IDecl;
+ llvm::SmallVectorImpl<DeclPtrTy> &Props;
+ ObjCDeclSpec &OCDS;
+ SourceLocation AtLoc;
+ tok::ObjCKeywordKind MethodImplKind;
+
+ ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
+ llvm::SmallVectorImpl<DeclPtrTy> &Props,
+ ObjCDeclSpec &OCDS, SourceLocation AtLoc,
+ tok::ObjCKeywordKind MethodImplKind) :
+ P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
+ MethodImplKind(MethodImplKind) {
+ }
+
+ DeclPtrTy invoke(FieldDeclarator &FD) {
+ if (FD.D.getIdentifier() == 0) {
+ P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+ if (FD.BitfieldSize) {
+ P.Diag(AtLoc, diag::err_objc_property_bitfield)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+
+ // Install the property declarator into interfaceDecl.
+ IdentifierInfo *SelName =
+ OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
+
+ Selector GetterSel =
+ P.PP.getSelectorTable().getNullarySelector(SelName);
+ IdentifierInfo *SetterName = OCDS.getSetterName();
+ Selector SetterSel;
+ if (SetterName)
+ SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
+ else
+ SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
+ P.PP.getSelectorTable(),
+ FD.D.getIdentifier());
+ bool isOverridingProperty = false;
+ DeclPtrTy Property =
+ P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
+ GetterSel, SetterSel, IDecl,
+ &isOverridingProperty,
+ MethodImplKind);
+ if (!isOverridingProperty)
+ Props.push_back(Property);
+
+ return Property;
+ }
+ } Callback(*this, interfaceDecl, allProperties,
+ OCDS, AtLoc, MethodImplKind);
+
// Parse all the comma separated declarators.
DeclSpec DS;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
- ParseStructDeclaration(DS, FieldDeclarators);
+ ParseStructDeclaration(DS, Callback);
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
tok::at);
-
- // Convert them all to property declarations.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- if (FD.D.getIdentifier() == 0) {
- Diag(AtLoc, diag::err_objc_property_requires_field_name)
- << FD.D.getSourceRange();
- continue;
- }
- if (FD.BitfieldSize) {
- Diag(AtLoc, diag::err_objc_property_bitfield)
- << FD.D.getSourceRange();
- continue;
- }
-
- // Install the property declarator into interfaceDecl.
- IdentifierInfo *SelName =
- OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
-
- Selector GetterSel =
- PP.getSelectorTable().getNullarySelector(SelName);
- IdentifierInfo *SetterName = OCDS.getSetterName();
- Selector SetterSel;
- if (SetterName)
- SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
- else
- SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(),
- FD.D.getIdentifier());
- bool isOverridingProperty = false;
- DeclPtrTy Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
- GetterSel, SetterSel,
- interfaceDecl,
- &isOverridingProperty,
- MethodImplKind);
- if (!isOverridingProperty)
- allProperties.push_back(Property);
- }
break;
}
}
@@ -681,6 +698,8 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
tok::TokenKind mType,
DeclPtrTy IDecl,
tok::ObjCKeywordKind MethodImplKind) {
+ ParsingDeclRAIIObject PD(*this);
+
// Parse the return type if present.
TypeTy *ReturnType = 0;
ObjCDeclSpec DSRet;
@@ -707,10 +726,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
MethodAttrs = ParseAttributes();
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
- return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+ DeclPtrTy Result
+ = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
0, CargNames, MethodAttrs,
MethodImplKind);
+ PD.complete(Result);
+ return Result;
}
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
@@ -783,10 +805,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
return DeclPtrTy();
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
- return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+ DeclPtrTy Result
+ = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
&ArgInfos[0], CargNames, MethodAttrs,
MethodImplKind, isVariadic);
+ PD.complete(Result);
+ return Result;
}
/// objc-protocol-refs:
@@ -858,7 +883,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {");
llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
@@ -893,21 +917,31 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
}
}
+ struct ObjCIvarCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy IDecl;
+ tok::ObjCKeywordKind visibility;
+ llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls;
+
+ ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
+ llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) :
+ P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
+ }
+
+ DeclPtrTy invoke(FieldDeclarator &FD) {
+ // Install the declarator into the interface decl.
+ DeclPtrTy Field
+ = P.Actions.ActOnIvar(P.CurScope,
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ IDecl, FD.D, FD.BitfieldSize, visibility);
+ AllIvarDecls.push_back(Field);
+ return Field;
+ }
+ } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
+
// Parse all the comma separated declarators.
DeclSpec DS;
- FieldDeclarators.clear();
- ParseStructDeclaration(DS, FieldDeclarators);
-
- // Convert them all to fields.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- // Install the declarator into interfaceDecl.
- DeclPtrTy Field = Actions.ActOnIvar(CurScope,
- DS.getSourceRange().getBegin(),
- interfaceDecl,
- FD.D, FD.BitfieldSize, visibility);
- AllIvarDecls.push_back(Field);
- }
+ ParseStructDeclaration(DS, Callback);
if (Tok.is(tok::semi)) {
ConsumeToken();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 272be2f66017..7637382ac032 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -938,8 +938,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
- false);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 8e63fb89db31..045acd86ad0f 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -101,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// (and retrieves the outer template parameter list from its
// context).
bool isSpecialization = true;
+ bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
TemplateParameterDepthCounter Depth(TemplateParameterDepth);
do {
@@ -140,13 +141,16 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
if (!TemplateParams.empty()) {
isSpecialization = false;
++Depth;
+ } else {
+ LastParamListWasEmpty = true;
}
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
// Parse the actual template declaration.
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(&ParamLists,
- isSpecialization),
+ isSpecialization,
+ LastParamListWasEmpty),
DeclEnd, AS);
}
@@ -186,16 +190,18 @@ Parser::ParseSingleDeclarationAfterTemplate(
}
// Parse the declaration specifiers.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
if (Tok.is(tok::semi)) {
DeclEnd = ConsumeToken();
- return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(Decl);
+ return Decl;
}
// Parse the declarator.
- Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
+ ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
@@ -221,6 +227,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Eat the semi colon after the declaration.
ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+ DS.complete(ThisDecl);
return ThisDecl;
}
@@ -668,22 +675,23 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
///
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
SourceLocation TemplateKWLoc,
bool AllowTypeAnnotation) {
assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
- assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
+ assert(Template && Tok.is(tok::less) &&
"Parser isn't at the beginning of a template-id");
// Consume the template-name.
- IdentifierInfo *Name = Tok.getIdentifierInfo();
- SourceLocation TemplateNameLoc = ConsumeToken();
+ SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
- bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc,
+ bool Invalid = ParseTemplateIdAfterTemplateName(Template,
+ TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
TemplateArgIsType,
@@ -732,7 +740,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size());
TemplateId->TemplateNameLoc = TemplateNameLoc;
- TemplateId->Name = Name;
+ if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = TemplateName.Identifier;
+ TemplateId->Operator = OO_None;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
+ }
TemplateId->Template = Template.getAs<void*>();
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index bc737e9f0c80..335a6cf36254 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -526,7 +526,7 @@ bool Parser::isStartOfFunctionDefinition() {
Parser::DeclGroupPtrTy
Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -534,6 +534,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
if (Tok.is(tok::semi)) {
ConsumeToken();
DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -548,6 +549,9 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
SkipUntil(tok::semi); // FIXME: better skip?
return DeclGroupPtrTy();
}
+
+ DS.abort();
+
const char *PrevSpec = 0;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
@@ -567,58 +571,12 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+ DS.abort();
DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- // Parse the first declarator.
- Declarator DeclaratorInfo(DS, Declarator::FileContext);
- ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return DeclGroupPtrTy();
- }
-
- // If we have a declaration or declarator list, handle it.
- if (isDeclarationAfterDeclarator()) {
- // Parse the init-declarator-list for a normal declaration.
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
- // Eat the semi colon after the declaration.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
- return DG;
- }
-
- if (DeclaratorInfo.isFunctionDeclarator() &&
- isStartOfFunctionDefinition()) {
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
- Diag(Tok, diag::err_function_declared_typedef);
-
- if (Tok.is(tok::l_brace)) {
- // This recovery skips the entire function body. It would be nice
- // to simply call ParseFunctionDefinition() below, however Sema
- // assumes the declarator represents a function, not a typedef.
- ConsumeBrace();
- SkipUntil(tok::r_brace, true);
- } else {
- SkipUntil(tok::semi);
- }
- return DeclGroupPtrTy();
- }
- DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
- return Actions.ConvertDeclToDeclGroup(TheDecl);
- }
-
- if (DeclaratorInfo.isFunctionDeclarator())
- Diag(Tok, diag::err_expected_fn_body);
- else
- Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
- SkipUntil(tok::semi);
- return DeclGroupPtrTy();
+ return ParseDeclGroup(DS, Declarator::FileContext, true);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
@@ -635,7 +593,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
/// [C++] function-definition: [C++ 8.4]
/// decl-specifier-seq[opt] declarator function-try-block
///
-Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
+Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo) {
const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
@@ -687,6 +645,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
D)
: Actions.ActOnStartOfFunctionDef(CurScope, D);
+ // Break out of the ParsingDeclarator context before we parse the body.
+ D.complete(Res);
+
+ // Break out of the ParsingDeclSpec context, too. This const_cast is
+ // safe because we're always the sole owner.
+ D.getMutableDeclSpec().abort();
+
if (Tok.is(tok::kw_try))
return ParseFunctionTryBlock(Res);
@@ -981,17 +946,21 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// If this is a template-id, annotate with a template-id or type token.
if (NextToken().is(tok::less)) {
TemplateTy Template;
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
if (TemplateNameKind TNK
- = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(),
- Tok.getLocation(), &SS,
+ = Actions.isTemplateName(CurScope, SS, TemplateName,
/*ObjectType=*/0, EnteringContext,
- Template))
- if (AnnotateTemplateIdToken(Template, TNK, &SS)) {
+ Template)) {
+ // Consume the identifier.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
// If an unrecoverable error occurred, we need to return true here,
// because the token stream is in a damaged state. We may not return
// a valid identifier.
return Tok.isNot(tok::identifier);
}
+ }
}
// The current token, which is either an identifier or a
@@ -1065,3 +1034,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
PP.AnnotateCachedTokens(Tok);
return true;
}
+
+// Anchor the Parser::FieldCallback vtable to this translation unit.
+// We use a spurious method instead of the destructor because
+// destroying FieldCallbacks can actually be slightly
+// performance-sensitive.
+void Parser::FieldCallback::_anchor() {
+}
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index c78ab5b3e959..9b24d55f3ece 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -156,6 +156,17 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
case Result::RK_Keyword:
OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
break;
+
+ case Result::RK_Macro: {
+ OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ OS << " : " << CCS->getAsString();
+ delete CCS;
+ }
+ OS << '\n';
+ break;
+ }
}
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fc9c14f456bd..8104dd39d052 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -277,15 +277,20 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
PushDeclContext(S, Context.getTranslationUnitDecl());
if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+ DeclaratorInfo *DInfo;
+
// Install [u]int128_t for 64-bit targets.
+ DInfo = Context.getTrivialDeclaratorInfo(Context.Int128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("__int128_t"),
- Context.Int128Ty), TUScope);
+ DInfo), TUScope);
+
+ DInfo = Context.getTrivialDeclaratorInfo(Context.UnsignedInt128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("__uint128_t"),
- Context.UnsignedInt128Ty), TUScope);
+ DInfo), TUScope);
}
@@ -298,10 +303,10 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
PushOnScopeChains(SelTag, TUScope);
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
- TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
- SourceLocation(),
- &Context.Idents.get("SEL"),
- SelT);
+ DeclaratorInfo *SelInfo = Context.getTrivialDeclaratorInfo(SelT);
+ TypedefDecl *SelTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("SEL"), SelInfo);
PushOnScopeChains(SelTypedef, TUScope);
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
}
@@ -317,22 +322,23 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
}
// Create the built-in typedef for 'id'.
if (Context.getObjCIdType().isNull()) {
- TypedefDecl *IdTypedef =
- TypedefDecl::Create(
- Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
- Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
- );
+ QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+ DeclaratorInfo *IdInfo = Context.getTrivialDeclaratorInfo(IdT);
+ TypedefDecl *IdTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("id"), IdInfo);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
Context.ObjCIdRedefinitionType = Context.getObjCIdType();
}
// Create the built-in typedef for 'Class'.
if (Context.getObjCClassType().isNull()) {
- TypedefDecl *ClassTypedef =
- TypedefDecl::Create(
- Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
- Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
- );
+ QualType ClassType
+ = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy);
+ DeclaratorInfo *ClassInfo = Context.getTrivialDeclaratorInfo(ClassType);
+ TypedefDecl *ClassTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("Class"), ClassInfo);
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
Context.ObjCClassRedefinitionType = Context.getObjCClassType();
@@ -344,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(0), CurContext(0),
- PreDeclaratorDC(0), CurBlock(0), PackContext(0),
+ PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6dd081bdc25e..0f84b46ed405 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -73,6 +73,7 @@ namespace clang {
class TypedefDecl;
class TemplateDecl;
class TemplateArgument;
+ class TemplateArgumentLoc;
class TemplateArgumentList;
class TemplateParameterList;
class TemplateTemplateParmDecl;
@@ -271,6 +272,15 @@ public:
llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
std::vector<DeclarationName> TentativeDefinitionList;
+ /// \brief The collection of delayed deprecation warnings.
+ llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8>
+ DelayedDeprecationWarnings;
+
+ /// \brief The depth of the current ParsingDeclaration stack.
+ /// If nonzero, we are currently parsing a declaration (and
+ /// hence should delay deprecation warnings).
+ unsigned ParsingDeclDepth;
+
/// WeakUndeclaredIdentifiers - Identifiers contained in
/// #pragma weak before declared. rare. may alias another
/// identifier, declared or undeclared
@@ -447,8 +457,6 @@ public:
// Type Analysis / Processing: SemaType.cpp.
//
QualType adjustParameterType(QualType T);
- QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
- bool &IsInvalid);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
@@ -470,12 +478,12 @@ public:
SourceLocation Loc, DeclarationName Entity);
QualType GetTypeForDeclarator(Declarator &D, Scope *S,
DeclaratorInfo **DInfo = 0,
- unsigned Skip = 0, TagDecl **OwnedDecl = 0);
- DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T,
- unsigned Skip);
+ TagDecl **OwnedDecl = 0);
+ DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T);
/// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
DeclarationName GetNameForDeclarator(Declarator &D);
+ DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
@@ -767,7 +775,8 @@ public:
/// Subroutines of ActOnDeclarator().
- TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ DeclaratorInfo *DInfo);
void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
@@ -868,7 +877,7 @@ public:
bool ForceRValue = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -876,7 +885,7 @@ public:
bool ForceRValue = false);
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -914,7 +923,7 @@ public:
void AddArgumentDependentLookupCandidates(DeclarationName Name,
Expr **Args, unsigned NumArgs,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading = false);
@@ -936,7 +945,7 @@ public:
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -945,7 +954,7 @@ public:
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -963,6 +972,10 @@ public:
FunctionSet &Functions,
Expr *LHS, Expr *RHS);
+ OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base,ExprArg Idx);
+
ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
SourceLocation LParenLoc, Expr **Args,
@@ -990,7 +1003,7 @@ public:
void CheckCXXDefaultArguments(FunctionDecl *FD);
void CheckExtraCXXDefaultArguments(Declarator &D);
enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
- AlwaysFallThrough = 2 };
+ AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
ControlFlowKind CheckFallThrough(Stmt *);
Scope *getNonFieldDeclScope(Scope *S);
@@ -1377,7 +1390,7 @@ public:
QualType T1, QualType T2,
FunctionSet &Functions);
- void ArgumentDependentLookup(DeclarationName Name,
+ void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions);
@@ -1582,6 +1595,10 @@ public:
/// whose result is unused, warn.
void DiagnoseUnusedExprResult(const Stmt *S);
+ ParsingDeclStackState PushParsingDeclaration();
+ void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
+ void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -1604,23 +1621,12 @@ public:
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
- virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS = 0,
- bool isAddressOfOperand = false);
- virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(Scope *S,
- SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand);
- virtual OwningExprResult ActOnCXXConversionFunctionExpr(Scope *S,
- SourceLocation OperatorLoc,
- TypeTy *Ty,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand);
+ virtual OwningExprResult ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand);
+
OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
SourceLocation Loc, bool TypeDependent,
bool ValueDependent,
@@ -1664,7 +1670,8 @@ public:
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, ExprArg Input);
- OwningExprResult CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+ OwningExprResult CreateSizeOfAlignOfExpr(DeclaratorInfo *T,
+ SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
@@ -1684,6 +1691,10 @@ public:
SourceLocation LLoc,
ExprArg Idx,
SourceLocation RLoc);
+ OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base,
+ SourceLocation LLoc,
+ ExprArg Idx,
+ SourceLocation RLoc);
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
@@ -1709,20 +1720,21 @@ public:
DeclarationName MemberName,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
DeclPtrTy ImplDecl,
const CXXScopeSpec *SS,
NamedDecl *FirstQualifierInScope = 0);
- virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ImplDecl,
- const CXXScopeSpec *SS = 0);
+ virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen);
+
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
@@ -1742,7 +1754,7 @@ public:
SourceRange &QualifierRange,
bool &ArgumentDependentLookup,
bool &HasExplicitTemplateArguments,
- const TemplateArgument *&ExplicitTemplateArgs,
+ const TemplateArgumentLoc *&ExplicitTemplateArgs,
unsigned &NumExplicitTemplateArgs);
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
@@ -1900,7 +1912,6 @@ public:
/// and sets it as the initializer for the the passed in VarDecl.
bool InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
- QualType DeclInitType,
MultiExprArg Exprs);
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -2099,52 +2110,6 @@ public:
tok::TokenKind OpKind,
TypeTy *&ObjectType);
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen);
-
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *Type,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen);
-
- virtual OwningExprResult
- ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS = 0);
- virtual OwningExprResult
- ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS = 0);
-
- virtual OwningExprResult
- ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- // FIXME: "template" keyword?
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc);
-
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
@@ -2305,7 +2270,7 @@ public:
SourceLocation RParenLoc,
CXXRecordDecl *ClassDecl);
- void setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+ void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
@@ -2445,9 +2410,8 @@ public:
// C++ Templates [C++ 14]
//
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template);
@@ -2507,13 +2471,13 @@ public:
AccessSpecifier AS);
void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- llvm::SmallVector<TemplateArgument, 16> &TemplateArgs);
+ SourceLocation *TemplateArgLocsIn,
+ llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs);
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -2534,22 +2498,21 @@ public:
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
- virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc);
+ OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType);
bool CheckClassTemplatePartialSpecializationArgs(
@@ -2578,10 +2541,18 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew);
+
bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
NamedDecl *&PrevDecl);
@@ -2621,18 +2592,18 @@ public:
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc,
bool PartialTemplateArgs,
TemplateArgumentListBuilder &Converted);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgument &Arg,
+ const TemplateArgumentLoc &Arg,
TemplateArgumentListBuilder &Converted);
- bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg,
- SourceLocation ArgLoc);
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ DeclaratorInfo *Arg);
bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
NamedDecl *&Entity);
bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
@@ -2807,7 +2778,7 @@ public:
TemplateDeductionResult
SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
llvm::SmallVectorImpl<TemplateArgument> &Deduced,
llvm::SmallVectorImpl<QualType> &ParamTypes,
@@ -2823,7 +2794,7 @@ public:
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
@@ -2832,7 +2803,7 @@ public:
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
@@ -2863,6 +2834,7 @@ public:
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used);
void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
llvm::SmallVectorImpl<bool> &Deduced);
@@ -3101,7 +3073,7 @@ public:
llvm::DenseMap<const Decl *, Decl *> LocalDecls;
/// \brief The outer scope, in which contains local variable
- /// definitions from some other instantiation (that is not
+ /// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
@@ -3110,9 +3082,13 @@ public:
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
- LocalInstantiationScope(Sema &SemaRef)
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
- SemaRef.CurrentInstantiationScope = this;
+ if (!CombineWithOuterScope)
+ SemaRef.CurrentInstantiationScope = this;
+ else
+ assert(SemaRef.CurrentInstantiationScope &&
+ "No outer instantiation scope?");
}
~LocalInstantiationScope() {
@@ -3133,6 +3109,11 @@ public:
return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
+ NonTypeTemplateParmDecl *getInstantiationOf(
+ const NonTypeTemplateParmDecl *Var) {
+ return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
void InstantiatedLocal(const Decl *D, Decl *Inst) {
Decl *&Stored = LocalDecls[D];
assert(!Stored && "Already instantiated this local");
@@ -3190,7 +3171,7 @@ public:
bool Complain = true);
bool
- InstantiateClassTemplateSpecialization(
+ InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain = true);
@@ -3213,8 +3194,8 @@ public:
TemplateName
SubstTemplateName(TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs);
- TemplateArgument Subst(TemplateArgument Arg,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index bf396041b473..8bb334855d02 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -83,7 +83,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType,
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
- unsigned &msg);
+ unsigned &msg,
+ CastExpr::CastKind &Kind);
static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
@@ -480,7 +481,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
// conversion. C++ 5.2.9p9 has additional information.
// DR54's access restrictions apply here also.
tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle,
- OpRange, msg);
+ OpRange, msg, Kind);
if (tcr != TC_NotApplicable)
return tcr;
@@ -706,7 +707,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
TryCastResult
TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg) {
+ unsigned &msg, CastExpr::CastKind &Kind) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
if (!DestMemPtr)
return TC_NotApplicable;
@@ -760,6 +761,7 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
return TC_Failed;
}
+ Kind = CastExpr::CK_DerivedToBaseMemberPointer;
return TC_Success;
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 589b0c6bd0ec..38b6ebeefab9 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1272,10 +1272,15 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
// Skip over implicit cast expressions when checking for block expressions.
RetValExp = RetValExp->IgnoreParenCasts();
- if (BlockExpr *C = dyn_cast_or_null<BlockExpr>(RetValExp))
+ if (BlockExpr *C = dyn_cast<BlockExpr>(RetValExp))
if (C->hasBlockDeclRefExprs())
Diag(C->getLocStart(), diag::err_ret_local_block)
<< C->getSourceRange();
+
+ if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp))
+ Diag(ALE->getLocStart(), diag::warn_ret_addr_label)
+ << ALE->getSourceRange();
+
} else if (lhsType->isReferenceType()) {
// Perform checking for stack values returned by reference.
// Check for a reference to the stack
@@ -1420,8 +1425,7 @@ static DeclRefExpr* EvalVal(Expr *E) {
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass: {
+ case Stmt::DeclRefExprClass: {
// DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking
// at code that refers to a variable's name. We check if it has local
// storage within the function, and if so, return the expression.
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 381151325a03..e9df17d6a115 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -13,6 +13,8 @@
#include "Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include <list>
@@ -801,9 +803,45 @@ void AddQualifierToCompletionString(CodeCompletionString *Result,
/// result is all that is needed.
CodeCompletionString *
CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
- if (Kind != RK_Declaration)
+ if (Kind == RK_Keyword)
return 0;
+ if (Kind == RK_Macro) {
+ MacroInfo *MI = S.PP.getMacroInfo(Macro);
+ if (!MI || !MI->isFunctionLike())
+ return 0;
+
+ // Format a function-like macro with placeholders for the arguments.
+ CodeCompletionString *Result = new CodeCompletionString;
+ Result->AddTextChunk(Macro->getName().str().c_str());
+ Result->AddTextChunk("(");
+ for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+ A != AEnd; ++A) {
+ if (A != MI->arg_begin())
+ Result->AddTextChunk(", ");
+
+ if (!MI->isVariadic() || A != AEnd - 1) {
+ // Non-variadic argument.
+ Result->AddPlaceholderChunk((*A)->getName().str().c_str());
+ continue;
+ }
+
+ // Variadic argument; cope with the different between GNU and C99
+ // variadic macros, providing a single placeholder for the rest of the
+ // arguments.
+ if ((*A)->isStr("__VA_ARGS__"))
+ Result->AddPlaceholderChunk("...");
+ else {
+ std::string Arg = (*A)->getName();
+ Arg += "...";
+ Result->AddPlaceholderChunk(Arg.c_str());
+ }
+ }
+ Result->AddTextChunk(")");
+ return Result;
+ }
+
+ assert(Kind == RK_Declaration && "Missed a macro kind?");
NamedDecl *ND = Declaration;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -999,6 +1037,10 @@ namespace {
case Result::RK_Keyword:
return strcmp(X.Keyword, Y.Keyword) < 0;
+
+ case Result::RK_Macro:
+ return llvm::LowercaseString(X.Macro->getName()) <
+ llvm::LowercaseString(Y.Macro->getName());
}
// Silence GCC warning.
@@ -1007,6 +1049,16 @@ namespace {
};
}
+// Add all of the known macros as code-completion results.
+static void AddMacroResults(Preprocessor &PP, unsigned Rank,
+ ResultBuilder &Results) {
+ Results.EnterNewScope();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
+ M != MEnd; ++M)
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
+ Results.ExitScope();
+}
+
static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
CodeCompleteConsumer::Result *Results,
unsigned NumResults) {
@@ -1019,8 +1071,9 @@ static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
void Sema::CodeCompleteOrdinaryName(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1076,6 +1129,9 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
CurContext, Results);
}
+ // Add macros
+ AddMacroResults(PP, NextRank, Results);
+
// Hand off the results found for code completion.
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
@@ -1117,10 +1173,11 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- CurContext, Results);
+ NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ NextRank, CurContext, Results);
}
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1171,8 +1228,7 @@ void Sema::CodeCompleteCase(Scope *S) {
// At the XXX, our completions are TagDecl::TK_union,
// TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
// TK_struct, and TK_class.
- if (QualifiedDeclRefExpr *QDRE = dyn_cast<QualifiedDeclRefExpr>(DRE))
- Qualifier = QDRE->getQualifier();
+ Qualifier = DRE->getQualifier();
}
}
@@ -1199,6 +1255,7 @@ void Sema::CodeCompleteCase(Scope *S) {
}
Results.ExitScope();
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1235,7 +1292,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
SourceRange QualifierRange;
bool ArgumentDependentLookup;
bool HasExplicitTemplateArgs;
- const TemplateArgument *ExplicitTemplateArgs;
+ const TemplateArgumentLoc *ExplicitTemplateArgs;
unsigned NumExplicitTemplateArgs;
DeconstructCallFunction(Fn,
@@ -1293,6 +1350,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
if (!Results.empty() && NNS->isDependent())
Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
+ AddMacroResults(PP, NextRank + 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1309,10 +1367,11 @@ void Sema::CodeCompleteUsing(Scope *S) {
// After "using", we can see anything that would start a
// nested-name-specifier.
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0,
- CurContext, Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1324,9 +1383,10 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
// alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
Results.EnterNewScope();
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1361,6 +1421,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Results.ExitScope();
}
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1370,8 +1431,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1398,10 +1460,11 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
// Add any nested-name-specifiers
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank + 1,
- CurContext, Results);
+ NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ NextRank + 1, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b83181becb93..d89cb5fc97f5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -95,7 +95,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::FoundOverloaded:
return 0;
- case LookupResult::Ambiguous: {
+ case LookupResult::Ambiguous:
// Recover from type-hiding ambiguities by hiding the type. We'll
// do the lookup again when looking for an object, and we can
// diagnose the error then. If we don't do this, then the error
@@ -131,51 +131,43 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// perform the name lookup again.
DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
break;
- }
case LookupResult::Found:
IIDecl = Result.getFoundDecl();
break;
}
- if (IIDecl) {
- QualType T;
-
- if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
- // Check whether we can use this type
- (void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
- if (getLangOptions().CPlusPlus) {
- // C++ [temp.local]p2:
- // Within the scope of a class template specialization or
- // partial specialization, when the injected-class-name is
- // not followed by a <, it is equivalent to the
- // injected-class-name followed by the template-argument s
- // of the class template specialization or partial
- // specialization enclosed in <>.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
- if (RD->isInjectedClassName())
- if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
- T = Template->getInjectedClassNameType(Context);
- }
-
- if (T.isNull())
- T = Context.getTypeDeclType(TD);
- } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
- // Check whether we can use this interface.
- (void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
- T = Context.getObjCInterfaceType(IDecl);
- } else
- return 0;
+ assert(IIDecl && "Didn't find decl");
+ QualType T;
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
+ DiagnoseUseOfDecl(IIDecl, NameLoc);
+
+ // C++ [temp.local]p2:
+ // Within the scope of a class template specialization or
+ // partial specialization, when the injected-class-name is
+ // not followed by a <, it is equivalent to the
+ // injected-class-name followed by the template-argument s
+ // of the class template specialization or partial
+ // specialization enclosed in <>.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
+ if (RD->isInjectedClassName())
+ if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
+ T = Template->getInjectedClassNameType(Context);
+
+ if (T.isNull())
+ T = Context.getTypeDeclType(TD);
+
if (SS)
T = getQualifiedNameType(*SS, T);
+
+ } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ DiagnoseUseOfDecl(IIDecl, NameLoc);
+ T = Context.getObjCInterfaceType(IDecl);
+ } else
+ return 0;
- return T.getAsOpaquePtr();
- }
-
- return 0;
+ return T.getAsOpaquePtr();
}
/// isTagName() - This method is called *for error recovery purposes only*
@@ -1055,9 +1047,11 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
/// Statement that should return a value.
///
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
-/// MaybeFallThrough iff we might or might not fall off the end and
-/// NeverFallThrough iff we never fall off the end of the statement. We assume
-/// that functions not marked noreturn will return.
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return. We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return. We assume that functions not marked noreturn
+/// will return.
Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
// FIXME: Eventually share this CFG object when we have other warnings based
// of the CFG. This can be done using AnalysisContext.
@@ -1065,7 +1059,8 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
// FIXME: They should never return 0, fix that, delete this code.
if (cfg == 0)
- return NeverFallThrough;
+ // FIXME: This should be NeverFallThrough
+ return NeverFallThroughOrReturn;
// The CFG leaves in dead things, and we don't want to dead code paths to
// confuse us, so we mark all live things first.
std::queue<CFGBlock*> workq;
@@ -1094,7 +1089,7 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
bool HasLiveReturn = false;
bool HasFakeEdge = false;
bool HasPlainEdge = false;
- for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(),
+ for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
E = cfg->getExit().pred_end();
I != E;
++I) {
@@ -1138,8 +1133,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
if (NoReturnEdge == false)
HasPlainEdge = true;
}
- if (!HasPlainEdge)
- return NeverFallThrough;
+ if (!HasPlainEdge) {
+ if (HasLiveReturn)
+ return NeverFallThrough;
+ return NeverFallThroughOrReturn;
+ }
if (HasFakeEdge || HasLiveReturn)
return MaybeFallThrough;
// This says AlwaysFallThrough for calls to functions that are not marked
@@ -1161,6 +1159,7 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
// which this code would then warn about.
if (getDiagnostics().hasErrorOccurred())
return;
+
bool ReturnsVoid = false;
bool HasNoReturn = false;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -1202,10 +1201,12 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
else if (!ReturnsVoid)
Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
break;
- case NeverFallThrough:
- if (ReturnsVoid)
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn)
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
break;
+ case NeverFallThrough:
+ break;
}
}
}
@@ -1225,7 +1226,7 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
return;
bool ReturnsVoid = false;
bool HasNoReturn = false;
- if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) {
+ if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
if (FT->getResultType()->isVoidType())
ReturnsVoid = true;
if (FT->getNoReturnAttr())
@@ -1253,10 +1254,12 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
else if (!ReturnsVoid)
Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
break;
- case NeverFallThrough:
+ case NeverFallThroughOrReturn:
if (ReturnsVoid)
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
break;
+ case NeverFallThrough:
+ break;
}
}
}
@@ -1330,6 +1333,10 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
}
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+ // If there are attributes in the DeclSpec, apply them to the record.
+ if (const AttributeList *AL = DS.getAttributes())
+ ProcessDeclAttributeList(S, Record, AL);
+
if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOptions().CPlusPlus ||
@@ -1602,53 +1609,60 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
/// GetNameForDeclarator - Determine the full declaration name for the
/// given Declarator.
DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
- switch (D.getKind()) {
- case Declarator::DK_Abstract:
- assert(D.getIdentifier() == 0 && "abstract declarators have no name");
- return DeclarationName();
-
- case Declarator::DK_Normal:
- assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
- return DeclarationName(D.getIdentifier());
-
- case Declarator::DK_Constructor: {
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Ty));
- }
-
- case Declarator::DK_Destructor: {
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(Ty));
- }
-
- case Declarator::DK_Conversion: {
- // FIXME: We'd like to keep the non-canonical type for diagnostics!
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXConversionFunctionName(
- Context.getCanonicalType(Ty));
- }
+ return GetNameFromUnqualifiedId(D.getName());
+}
- case Declarator::DK_Operator:
- assert(D.getIdentifier() == 0 && "operator names have no identifier");
- return Context.DeclarationNames.getCXXOperatorName(
- D.getOverloadedOperator());
+/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
+DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ return DeclarationName(Name.Identifier);
- case Declarator::DK_TemplateId: {
- TemplateName Name
- = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);
- if (TemplateDecl *Template = Name.getAsTemplateDecl())
- return Template->getDeclName();
- if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
- return Ovl->getDeclName();
-
- return DeclarationName();
- }
+ case UnqualifiedId::IK_OperatorFunctionId:
+ return Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator);
+
+ case UnqualifiedId::IK_ConversionFunctionId: {
+ QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_ConstructorName: {
+ QualType Ty = GetTypeFromParser(Name.ConstructorName);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ QualType Ty = GetTypeFromParser(Name.DestructorName);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_TemplateId: {
+ TemplateName TName
+ = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
+ if (TemplateDecl *Template = TName.getAsTemplateDecl())
+ return Template->getDeclName();
+ if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
+ return Ovl->getDeclName();
+
+ return DeclarationName();
+ }
}
-
+
assert(false && "Unknown name kind");
- return DeclarationName();
+ return DeclarationName();
}
/// isNearlyMatchingFunction - Determine whether the C++ functions
@@ -1986,12 +2000,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, DInfo);
if (!NewTD) return 0;
- if (D.isInvalidType())
- NewTD->setInvalidDecl();
-
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
// Merge the decl with the existing one if appropriate. If the decl is
@@ -2013,7 +2024,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
if (!FixedTy.isNull()) {
Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
- NewTD->setUnderlyingType(FixedTy);
+ NewTD->setTypeDeclaratorInfo(Context.getTrivialDeclaratorInfo(FixedTy));
} else {
if (SizeIsNegative)
Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
@@ -2516,7 +2527,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isInline |= IsFunctionDefinition;
}
- if (D.getKind() == Declarator::DK_Constructor) {
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
@@ -2529,7 +2540,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
D.getIdentifierLoc(), Name, R, DInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
- } else if (D.getKind() == Declarator::DK_Destructor) {
+ } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
R = CheckDestructorDeclarator(D, SC);
@@ -2551,7 +2562,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/*hasPrototype=*/true);
D.setInvalidType();
}
- } else if (D.getKind() == Declarator::DK_Conversion) {
+ } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
if (!DC->isRecord()) {
Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
@@ -2795,10 +2806,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
SourceLocation LAngleLoc, RAngleLoc;
- if (D.getKind() == Declarator::DK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getTemplateId();
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
@@ -3101,7 +3112,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
// C99 6.7.4p4: In a hosted environment, the inline function specifier
// shall not appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
- bool isInline = FD->isInline();
+ bool isInline = FD->isInlineSpecified();
bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
if (isInline || isStatic) {
unsigned diagID = diag::warn_unusual_main_decl;
@@ -3442,7 +3453,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
if (getLangOptions().CPlusPlus) {
QualType InitType = Type;
if (const ArrayType *Array = Context.getAsArrayType(Type))
- InitType = Array->getElementType();
+ InitType = Context.getBaseElementType(Array);
if ((!Var->hasExternalStorage() && !Var->isExternC()) &&
InitType->isRecordType() && !InitType->isDependentType()) {
if (!RequireCompleteType(Var->getLocation(), InitType,
@@ -3465,7 +3476,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
else {
// FIXME: Cope with initialization of arrays
if (!Constructor->isTrivial() &&
- InitializeVarWithConstructor(Var, Constructor, InitType,
+ InitializeVarWithConstructor(Var, Constructor,
move_arg(ConstructorArgs)))
Var->setInvalidDecl();
@@ -3626,8 +3637,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
DeclaratorInfo *DInfo = 0;
TagDecl *OwnedDecl = 0;
- QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0,
- &OwnedDecl);
+ QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, &OwnedDecl);
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
// C++ [dcl.fct]p6:
@@ -3668,16 +3678,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
QualType T = adjustParameterType(parmDeclType);
- ParmVarDecl *New;
- if (T == parmDeclType) // parameter type did not need adjustment
- New = ParmVarDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), II,
- parmDeclType, DInfo, StorageClass,
- 0);
- else // keep track of both the adjusted and unadjusted types
- New = OriginalParmVarDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), II, T, DInfo,
- parmDeclType, StorageClass, 0);
+ ParmVarDecl *New
+ = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II,
+ T, DInfo, StorageClass, 0);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -3776,6 +3779,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
}
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+ // Clear the last template instantiation error context.
+ LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
+
if (!D)
return D;
FunctionDecl *FD = 0;
@@ -4104,15 +4110,21 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
}
}
-TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ DeclaratorInfo *DInfo) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
+ if (!DInfo) {
+ assert(D.isInvalidType() && "no declarator info for valid type");
+ DInfo = Context.getTrivialDeclaratorInfo(T);
+ }
+
// Scope manipulation handled by caller.
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
D.getIdentifierLoc(),
D.getIdentifier(),
- T);
+ DInfo);
if (const TagType *TT = T->getAs<TagType>()) {
TagDecl *TD = TT->getDecl();
@@ -4321,9 +4333,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (PrevDecl) {
- // Check whether the previous declaration is usable.
- (void)DiagnoseUseOfDecl(PrevDecl, NameLoc);
-
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
@@ -4955,12 +4964,16 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
case CXXDefaultConstructor:
if (RD->hasUserDeclaredConstructor()) {
typedef CXXRecordDecl::ctor_iterator ctor_iter;
- for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce; ++ci)
- if (!ci->isImplicitlyDefined(Context)) {
+ for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
+ const FunctionDecl *body = 0;
+ ci->getBody(body);
+ if (!body ||
+ !cast<CXXConstructorDecl>(body)->isImplicitlyDefined(Context)) {
SourceLocation CtorLoc = ci->getLocation();
Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
return;
}
+ }
assert(0 && "found no user-declared constructors");
return;
@@ -5038,7 +5051,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
// Check for nontrivial bases (and recurse).
for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
- assert(BaseRT);
+ assert(BaseRT && "Don't know how to handle dependent bases");
CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
if (!(BaseRecTy->*hasTrivial)()) {
SourceLocation BaseLoc = bi->getSourceRange().getBegin();
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 341d49ead418..18f57da76912 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -193,7 +193,8 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
// This will run the reguired checks.
QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
if (!T.isNull()) {
- tDecl->setUnderlyingType(T);
+ // FIXME: preserve the old source info.
+ tDecl->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(T));
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(tDecl);
@@ -278,8 +279,11 @@ static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
VD->setType(CurType);
- else
- cast<TypedefDecl>(D)->setUnderlyingType(CurType);
+ else {
+ // FIXME: preserve existing source info.
+ DeclaratorInfo *DInfo = S.Context.getTrivialDeclaratorInfo(CurType);
+ cast<TypedefDecl>(D)->setTypeDeclaratorInfo(DInfo);
+ }
}
static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -897,7 +901,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Currently, the dllimport attribute is ignored for inlined functions.
// Warning is emitted.
- if (FD->isInline()) {
+ if (FD->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
return;
}
@@ -942,7 +946,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Currently, the dllexport attribute is ignored for inlined functions, unless
// the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD->isInline()) {
+ if (FD->isInlineSpecified()) {
// FIXME: ... unless the -fkeep-inline-functions flag has been used.
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
return;
@@ -1028,6 +1032,22 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) StdCallAttr());
}
+/// Diagnose the use of a non-standard calling convention on the given
+/// function.
+static void DiagnoseCConv(FunctionDecl *D, const char *CConv,
+ SourceLocation Loc, Sema &S) {
+ if (!D->hasPrototype()) {
+ S.Diag(Loc, diag::err_cconv_knr) << CConv;
+ return;
+ }
+
+ const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>();
+ if (T->isVariadic()) {
+ S.Diag(Loc, diag::err_cconv_varargs) << CConv;
+ return;
+ }
+}
+
static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// Attribute has no arguments.
if (Attr.getNumArgs() != 0) {
@@ -1041,6 +1061,8 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
+ DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S);
+
// stdcall and fastcall attributes are mutually incompatible.
if (d->getAttr<StdCallAttr>()) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
@@ -1636,9 +1658,10 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
// Install the new type.
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
- TD->setUnderlyingType(NewTy);
- else
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ // FIXME: preserve existing source info.
+ TD->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(NewTy));
+ } else
cast<ValueDecl>(D)->setType(NewTy);
}
@@ -1688,7 +1711,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- if (!Fn->isInline()) {
+ if (!Fn->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
}
@@ -1944,3 +1967,62 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
if (const AttributeList *Attrs = PD.getAttributes())
ProcessDeclAttributeList(S, D, Attrs);
}
+
+/// PushParsingDeclaration - Enter a new "scope" of deprecation
+/// warnings.
+///
+/// The state token we use is the start index of this scope
+/// on the warning stack.
+Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
+ ParsingDeclDepth++;
+ return (ParsingDeclStackState) DelayedDeprecationWarnings.size();
+}
+
+static bool isDeclDeprecated(Decl *D) {
+ do {
+ if (D->hasAttr<DeprecatedAttr>())
+ return true;
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
+void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
+ assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
+ ParsingDeclDepth--;
+
+ if (DelayedDeprecationWarnings.empty())
+ return;
+
+ unsigned SavedIndex = (unsigned) S;
+ assert(SavedIndex <= DelayedDeprecationWarnings.size() &&
+ "saved index is out of bounds");
+
+ if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) {
+ for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) {
+ SourceLocation Loc = DelayedDeprecationWarnings[I].first;
+ NamedDecl *&ND = DelayedDeprecationWarnings[I].second;
+ if (ND) {
+ Diag(Loc, diag::warn_deprecated) << ND->getDeclName();
+
+ // Prevent this from triggering multiple times.
+ ND = 0;
+ }
+ }
+ }
+
+ DelayedDeprecationWarnings.set_size(SavedIndex);
+}
+
+void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
+ // Delay if we're currently parsing a declaration.
+ if (ParsingDeclDepth) {
+ DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D));
+ return;
+ }
+
+ // Otherwise, don't warn if our current context is deprecated.
+ if (isDeclDeprecated(cast<Decl>(CurContext)))
+ return;
+
+ Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6d1f4ea4a865..bc255137fccf 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1123,7 +1123,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
}
void
-Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
@@ -1179,7 +1179,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
AllToInit.push_back(Value);
@@ -1187,18 +1187,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
else {
CXXRecordDecl *VBaseDecl =
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
+ assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
- if (!Ctor)
+ if (!Ctor) {
Bases.push_back(VBase);
- else
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ continue;
+ }
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
+ MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
- Ctor,
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(VBase->getType(),
+ CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
AllToInit.push_back(Member);
}
}
@@ -1216,7 +1224,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
AllToInit.push_back(Value);
@@ -1224,18 +1232,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
else {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
- if (!Ctor)
+ if (!Ctor) {
Bases.push_back(Base);
- else
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ continue;
+ }
+
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
+ MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
- BaseDecl->getDefaultConstructor(Context),
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(Base->getType(),
+ CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
AllToInit.push_back(Member);
}
}
@@ -1268,7 +1284,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
QualType FT = (*Field)->getType();
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl());
- assert(FieldRecDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor =
FieldRecDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
@@ -1281,13 +1297,22 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXConstructorDecl *Ctor =
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor && !FT->isDependentType())
+ if (!Ctor && !FT->isDependentType()) {
Fields.push_back(*Field);
+ continue;
+ }
+
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer((*Field), 0, 0,
- Ctor,
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
+
AllToInit.push_back(Member);
if (Ctor)
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
@@ -1327,10 +1352,10 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers
) {
- llvm::SmallVector<CXXBaseSpecifier *, 4>Bases;
- llvm::SmallVector<FieldDecl *, 4>Members;
+ llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
+ llvm::SmallVector<FieldDecl *, 4> Members;
- setBaseOrMemberInitializers(Constructor,
+ SetBaseOrMemberInitializers(Constructor,
Initializers, NumInitializers, Bases, Members);
for (unsigned int i = 0; i < Bases.size(); i++)
Diag(Bases[i]->getSourceRange().getBegin(),
@@ -1976,6 +2001,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
// and
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
+ assert(!Base->getType()->isDependentType() &&
+ "Cannot generate implicit members for class with dependent bases.");
const CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
const CXXMethodDecl *MD = 0;
@@ -2268,7 +2295,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
// (7.1.3); however, a typedef-name that names a class shall not
// be used as the identifier in the declarator for a destructor
// declaration.
- QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType());
+ QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
if (isa<TypedefType>(DeclaratorType)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType;
@@ -2394,7 +2421,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// C++ [class.conv.fct]p4:
// The conversion-type-id shall not represent a function type nor
// an array type.
- QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType());
+ QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
if (ConvType->isArrayType()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
ConvType = Context.getPointerType(ConvType);
@@ -3152,10 +3179,9 @@ Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor,
bool Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
- QualType DeclInitType,
MultiExprArg Exprs) {
OwningExprResult TempResult =
- BuildCXXConstructExpr(VD->getLocation(), DeclInitType, Constructor,
+ BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
move(Exprs));
if (TempResult.isInvalid())
return true;
@@ -3235,7 +3261,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
// class type.
QualType DeclInitType = VDecl->getType();
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
- DeclInitType = Array->getElementType();
+ DeclInitType = Context.getBaseElementType(Array);
// FIXME: This isn't the right place to complete the type.
if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
@@ -3260,7 +3286,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
RealDecl->setInvalidDecl();
else {
VDecl->setCXXDirectInitializer(true);
- if (InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
+ if (InitializeVarWithConstructor(VDecl, Constructor,
move_arg(ConstructorArgs)))
RealDecl->setInvalidDecl();
FinalizeVarWithDestructor(VDecl, DeclInitType);
@@ -4269,8 +4295,7 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
/// We permit this as a special case; if there are any template
/// parameters present at all, require proper matching, i.e.
/// template <> template <class T> friend class A<int>::B;
-Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS,
+Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TempParams) {
SourceLocation Loc = DS.getSourceRange().getBegin();
@@ -4280,9 +4305,10 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- bool invalid = false;
- QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
- if (invalid) return DeclPtrTy();
+ Declarator TheDeclarator(DS, Declarator::MemberContext);
+ QualType T = GetTypeForDeclarator(TheDeclarator, S);
+ if (TheDeclarator.isInvalidType())
+ return DeclPtrTy();
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
@@ -4489,12 +4515,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
if (DC->isFileContext()) {
// This implies that it has to be an operator or function.
- if (D.getKind() == Declarator::DK_Constructor ||
- D.getKind() == Declarator::DK_Destructor ||
- D.getKind() == Declarator::DK_Conversion) {
+ if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
Diag(Loc, diag::err_introducing_special_friend) <<
- (D.getKind() == Declarator::DK_Constructor ? 0 :
- D.getKind() == Declarator::DK_Destructor ? 1 : 2);
+ (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
return DeclPtrTy();
}
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 22a517934c7e..93f8d0dc37c1 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1707,29 +1707,22 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
llvm::SmallVector<ParmVarDecl*, 16> Params;
for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
- QualType ArgType, UnpromotedArgType;
+ QualType ArgType;
+ DeclaratorInfo *DI;
if (ArgInfo[i].Type == 0) {
- UnpromotedArgType = ArgType = Context.getObjCIdType();
+ ArgType = Context.getObjCIdType();
+ DI = 0;
} else {
- UnpromotedArgType = ArgType = GetTypeFromParser(ArgInfo[i].Type);
+ ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
// Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
ArgType = adjustParameterType(ArgType);
}
- ParmVarDecl* Param;
- if (ArgType == UnpromotedArgType)
- Param = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
- ArgInfo[i].Name, ArgType,
- /*DInfo=*/0, //FIXME: Pass info here.
- VarDecl::None, 0);
- else
- Param = OriginalParmVarDecl::Create(Context, ObjCMethod,
- ArgInfo[i].NameLoc,
- ArgInfo[i].Name, ArgType,
- /*DInfo=*/0, //FIXME: Pass info here.
- UnpromotedArgType,
- VarDecl::None, 0);
+ ParmVarDecl* Param
+ = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
+ ArgInfo[i].Name, ArgType, DI,
+ VarDecl::None, 0);
if (ArgType->isObjCInterfaceType()) {
Diag(ArgInfo[i].NameLoc,
@@ -1755,6 +1748,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
if (AttrList)
ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+ const ObjCMethodDecl *InterfaceMD = 0;
+
// For implementations (which can be very "coarse grain"), we add the
// method now. This allows the AST to implement lookup methods that work
// incrementally (without waiting until we parse the @end). It also allows
@@ -1768,6 +1763,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
PrevMethod = ImpDecl->getClassMethod(Sel);
ImpDecl->addClassMethod(ObjCMethod);
}
+ InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
+ MethodType == tok::minus);
if (AttrList)
Diag(EndLoc, diag::warn_attribute_method_def);
} else if (ObjCCategoryImplDecl *CatImpDecl =
@@ -1788,6 +1785,12 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
<< ObjCMethod->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
}
+
+ // If the interface declared this method, and it was deprecated there,
+ // mark it deprecated here.
+ if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
+ ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
+
return DeclPtrTy::make(ObjCMethod);
}
@@ -1900,33 +1903,34 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// handling.
if ((CCPrimary = CDecl->getClassInterface())) {
// Find the property in continuation class's primary class only.
- ObjCPropertyDecl *PIDecl = 0;
IdentifierInfo *PropertyId = FD.D.getIdentifier();
- for (ObjCInterfaceDecl::prop_iterator
- I = CCPrimary->prop_begin(), E = CCPrimary->prop_end();
- I != E; ++I)
- if ((*I)->getIdentifier() == PropertyId) {
- PIDecl = *I;
- break;
- }
-
- if (PIDecl) {
+ if (ObjCPropertyDecl *PIDecl =
+ CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) {
// property 'PIDecl's readonly attribute will be over-ridden
// with continuation class's readwrite property attribute!
unsigned PIkind = PIDecl->getPropertyAttributes();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
- if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) !=
- (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic))
+ unsigned assignRetainCopyNonatomic =
+ (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if ((Attributes & assignRetainCopyNonatomic) !=
+ (PIkind & assignRetainCopyNonatomic)) {
Diag(AtLoc, diag::warn_property_attr_mismatch);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
PIDecl->makeitReadWriteAttribute();
if (Attributes & ObjCDeclSpec::DQ_PR_retain)
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
PIDecl->setSetterName(SetterSel);
- } else
+ } else {
Diag(AtLoc, diag::err_use_continuation_class)
<< CCPrimary->getDeclName();
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
*isOverridingProperty = true;
// Make sure setter decl is synthesized, and added to primary
// class's list.
@@ -2054,6 +2058,14 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
return DeclPtrTy();
}
+ if (const ObjCCategoryDecl *CD =
+ dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
+ if (CD->getIdentifier()) {
+ Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+ Diag(property->getLocation(), diag::note_property_declare);
+ return DeclPtrTy();
+ }
+ }
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
Diag(AtLoc, diag::error_synthesize_category_decl);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ae45429952c7..ac7cced2eaef 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -37,40 +37,24 @@ using namespace clang;
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
+/// If IgnoreDeprecated is set to true, this should not want about deprecated
+/// decls.
+///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
+///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
if (D->getAttr<DeprecatedAttr>()) {
- // Implementing deprecated stuff requires referencing deprecated
- // stuff. Don't warn if we are implementing a deprecated
- // construct.
- bool isSilenced = false;
-
- if (NamedDecl *ND = getCurFunctionOrMethodDecl()) {
- // If this reference happens *in* a deprecated function or method, don't
- // warn.
- isSilenced = ND->getAttr<DeprecatedAttr>();
-
- // If this is an Objective-C method implementation, check to see if the
- // method was deprecated on the declaration, not the definition.
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND)) {
- // The semantic decl context of a ObjCMethodDecl is the
- // ObjCImplementationDecl.
- if (ObjCImplementationDecl *Impl
- = dyn_cast<ObjCImplementationDecl>(MD->getParent())) {
-
- MD = Impl->getClassInterface()->getMethod(MD->getSelector(),
- MD->isInstanceMethod());
- isSilenced |= MD && MD->getAttr<DeprecatedAttr>();
- }
- }
- }
-
- if (!isSilenced)
- Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+ EmitDeprecationWarning(D, Loc);
}
+ // See if the decl is unavailable
+ if (D->getAttr<UnavailableAttr>()) {
+ Diag(Loc, diag::warn_unavailable) << D->getDeclName();
+ Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+ }
+
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
@@ -80,12 +64,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
}
}
- // See if the decl is unavailable
- if (D->getAttr<UnavailableAttr>()) {
- Diag(Loc, diag::warn_unavailable) << D->getDeclName();
- Diag(D->getLocation(), diag::note_unavailable_here) << 0;
- }
-
return false;
}
@@ -432,23 +410,7 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
-/// ActOnIdentifierExpr - The parser read an identifier in expression context,
-/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
-/// identifier is used in a function call context.
-/// SS is only used for a C++ qualified-id (foo::bar) to indicate the
-/// class or namespace that the identifier must be a member of.
-Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand) {
- return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS,
- isAddressOfOperand);
-}
-
-/// BuildDeclRefExpr - Build either a DeclRefExpr or a
-/// QualifiedDeclRefExpr based on whether or not SS is a
-/// nested-name-specifier.
+/// BuildDeclRefExpr - Build a DeclRefExpr.
Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
@@ -476,15 +438,11 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
MarkDeclarationReferenced(Loc, D);
- Expr *E;
- if (SS && !SS->isEmpty()) {
- E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
- ValueDependent, SS->getRange(),
- static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
- } else
- E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
-
- return Owned(E);
+ return Owned(DeclRefExpr::Create(Context,
+ SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
+ SS? SS->getRange() : SourceRange(),
+ D, Loc,
+ Ty, TypeDependent, ValueDependent));
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
@@ -656,15 +614,43 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return Owned(Result);
}
+Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand) {
+ if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ Name.TemplateId->getTemplateArgs(),
+ Name.TemplateId->getTemplateArgIsType(),
+ Name.TemplateId->NumArgs);
+ return ActOnTemplateIdExpr(SS,
+ TemplateTy::make(Name.TemplateId->Template),
+ Name.TemplateId->TemplateNameLoc,
+ Name.TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ Name.TemplateId->getTemplateArgLocations(),
+ Name.TemplateId->RAngleLoc);
+ }
+
+ // FIXME: We lose a bunch of source information by doing this. Later,
+ // we'll want to merge ActOnDeclarationNameExpr's logic into
+ // ActOnIdExpression.
+ return ActOnDeclarationNameExpr(S,
+ Name.StartLocation,
+ GetNameFromUnqualifiedId(Name),
+ HasTrailingLParen,
+ &SS,
+ IsAddressOfOperand);
+}
+
/// ActOnDeclarationNameExpr - The parser has read some kind of name
/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
/// performs lookup on that name and returns an expression that refers
/// to that name. This routine isn't directly called from the parser,
/// because the parser doesn't know about DeclarationName. Rather,
-/// this routine is called by ActOnIdentifierExpr,
-/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr,
-/// which form the DeclarationName from the corresponding syntactic
-/// forms.
+/// this routine is called by ActOnIdExpression, which contains a
+/// parsed UnqualifiedId.
///
/// HasTrailingLParen indicates whether this identifier is used in a
/// function call context. LookupCtx is only used for a C++
@@ -745,8 +731,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
- OwningExprResult SelfExpr = ActOnIdentifierExpr(S, SourceLocation(),
- II, false);
+ UnqualifiedId SelfName;
+ SelfName.setIdentifier(&II, SourceLocation());
+ CXXScopeSpec SelfScopeSpec;
+ OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ SelfName, false, false);
MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
@@ -1083,7 +1072,8 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
// - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent
else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
- if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const &&
+ if (Context.getCanonicalType(Dcl->getType()).getCVRQualifiers()
+ == Qualifiers::Const &&
Dcl->getInit()) {
ValueDependent = Dcl->getInit()->isValueDependent();
}
@@ -1300,7 +1290,7 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
return false;
// C99 6.5.3.4p1:
- if (isa<FunctionType>(exprType)) {
+ if (exprType->isFunctionType()) {
// alignof(function) is allowed as an extension.
if (isSizeof)
Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
@@ -1358,17 +1348,20 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
/// \brief Build a sizeof or alignof expression given a type operand.
Action::OwningExprResult
-Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+Sema::CreateSizeOfAlignOfExpr(DeclaratorInfo *DInfo,
+ SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
- if (T.isNull())
+ if (!DInfo)
return ExprError();
+ QualType T = DInfo->getType();
+
if (!T->isDependentType() &&
CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, T,
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, DInfo,
Context.getSizeType(), OpLoc,
R.getEnd()));
}
@@ -1410,12 +1403,11 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
if (TyOrEx == 0) return ExprError();
if (isType) {
- // FIXME: Preserve type source info.
- QualType ArgTy = GetTypeFromParser(TyOrEx);
- return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange);
+ DeclaratorInfo *DInfo;
+ (void) GetTypeFromParser(TyOrEx, &DInfo);
+ return CreateSizeOfAlignOfExpr(DInfo, OpLoc, isSizeof, ArgRange);
}
- // Get the end location.
Expr *ArgEx = (Expr *)TyOrEx;
Action::OwningExprResult Result
= CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
@@ -1602,103 +1594,18 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
LHSExp->getType()->isEnumeralType() ||
RHSExp->getType()->isRecordType() ||
RHSExp->getType()->isEnumeralType())) {
- // Add the appropriate overloaded operators (C++ [over.match.oper])
- // to the candidate set.
- OverloadCandidateSet CandidateSet;
- Expr *Args[2] = { LHSExp, RHSExp };
- AddOperatorCandidates(OO_Subscript, S, LLoc, Args, 2, CandidateSet,
- SourceRange(LLoc, RLoc));
-
- // Perform overload resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, LLoc, Best)) {
- case OR_Success: {
- // We found a built-in operator or an overloaded operator.
- FunctionDecl *FnDecl = Best->Function;
-
- if (FnDecl) {
- // We matched an overloaded operator. Build a call to that
- // operator.
-
- // Convert the arguments.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- if (PerformObjectArgumentInitialization(LHSExp, Method) ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing"))
- return ExprError();
- } else {
- // Convert the arguments.
- if (PerformCopyInitialization(LHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing") ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(1)->getType(),
- "passing"))
- return ExprError();
- }
-
- // Determine the result type
- QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
-
- // Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
-
- Base.release();
- Idx.release();
- Args[0] = LHSExp;
- Args[1] = RHSExp;
-
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr, Args, 2,
- ResultTy, RLoc));
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
- FnDecl))
- return ExprError();
-
- return Owned(TheCall.release());
- } else {
- // We matched a built-in operator. Convert the arguments, then
- // break out so that we will build the appropriate built-in
- // operator node.
- if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0],
- "passing") ||
- PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1],
- "passing"))
- return ExprError();
-
- break;
- }
- }
-
- case OR_No_Viable_Function:
- // No viable function; fall through to handling this as a
- // built-in operator, which will produce an error message for us.
- break;
+ return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx));
+ }
- case OR_Ambiguous:
- Diag(LLoc, diag::err_ovl_ambiguous_oper)
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
+ return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+}
- case OR_Deleted:
- Diag(LLoc, diag::err_ovl_deleted_oper)
- << Best->Function->isDeleted()
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
- }
- // Either we found no viable overloaded operator or we matched a
- // built-in operator. In either case, fall through to trying to
- // build a built-in operation.
- }
+Action::OwningExprResult
+Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
+ ExprArg Idx, SourceLocation RLoc) {
+ Expr *LHSExp = static_cast<Expr*>(Base.get());
+ Expr *RHSExp = static_cast<Expr*>(Idx.get());
// Perform default conversions.
DefaultFunctionArrayConversion(LHSExp);
@@ -1961,7 +1868,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
DeclarationName MemberName,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS,
@@ -2549,13 +2456,77 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return ExprError();
}
-Action::OwningExprResult
-Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) {
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
- DeclarationName(&Member), ObjCImpDecl, SS);
+Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen) {
+ if (Member.getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateName Template
+ = TemplateName::getFromVoidPointer(Member.TemplateId->Template);
+
+ // FIXME: We're going to end up looking up the template based on its name,
+ // twice!
+ DeclarationName Name;
+ if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
+ Name = ActualTemplate->getDeclName();
+ else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
+ Name = Ovl->getDeclName();
+ else {
+ DependentTemplateName *DTN = Template.getAsDependentTemplateName();
+ if (DTN->isIdentifier())
+ Name = DTN->getIdentifier();
+ else
+ Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ }
+
+ // Translate the parser's template argument list in our AST format.
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ Member.TemplateId->getTemplateArgs(),
+ Member.TemplateId->getTemplateArgIsType(),
+ Member.TemplateId->NumArgs);
+
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsPtr,
+ Member.TemplateId->getTemplateArgLocations(),
+ TemplateArgs);
+ TemplateArgsPtr.release();
+
+ // Do we have the save the actual template name? We might need it...
+ return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ Member.TemplateId->TemplateNameLoc,
+ Name, true, Member.TemplateId->LAngleLoc,
+ TemplateArgs.data(), TemplateArgs.size(),
+ Member.TemplateId->RAngleLoc, DeclPtrTy(),
+ &SS);
+ }
+
+ // FIXME: We lose a lot of source information by mapping directly to the
+ // DeclarationName.
+ OwningExprResult Result
+ = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ Member.getSourceRange().getBegin(),
+ GetNameFromUnqualifiedId(Member),
+ ObjCImpDecl, &SS);
+
+ if (Result.isInvalid() || HasTrailingLParen ||
+ Member.getKind() != UnqualifiedId::IK_DestructorName)
+ return move(Result);
+
+ // The only way a reference to a destructor can be used is to
+ // immediately call them. Since the next token is not a '(', produce a
+ // diagnostic and build the call now.
+ Expr *E = (Expr *)Result.get();
+ SourceLocation ExpectedLParenLoc
+ = PP.getLocForEndOfToken(Member.getSourceRange().getEnd());
+ Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
+ << isa<CXXPseudoDestructorExpr>(E)
+ << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
+
+ return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
+ MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
}
Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -2713,7 +2684,7 @@ void Sema::DeconstructCallFunction(Expr *FnExpr,
SourceRange &QualifierRange,
bool &ArgumentDependentLookup,
bool &HasExplicitTemplateArguments,
- const TemplateArgument *&ExplicitTemplateArgs,
+ const TemplateArgumentLoc *&ExplicitTemplateArgs,
unsigned &NumExplicitTemplateArgs) {
// Set defaults for all of the output parameters.
Function = 0;
@@ -2738,16 +2709,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr,
cast<UnaryOperator>(FnExpr)->getOpcode()
== UnaryOperator::AddrOf) {
FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
- } else if (QualifiedDeclRefExpr *QDRExpr
- = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) {
- // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1).
- ArgumentDependentLookup = false;
- Qualifier = QDRExpr->getQualifier();
- QualifierRange = QDRExpr->getQualifierRange();
- Function = dyn_cast<NamedDecl>(QDRExpr->getDecl());
- break;
} else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
Function = dyn_cast<NamedDecl>(DRExpr->getDecl());
+ if ((Qualifier = DRExpr->getQualifier())) {
+ ArgumentDependentLookup = false;
+ QualifierRange = DRExpr->getQualifierRange();
+ }
break;
} else if (UnresolvedFunctionNameExpr *DepName
= dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) {
@@ -2866,24 +2833,29 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) {
if (BO->getOpcode() == BinaryOperator::PtrMemD ||
BO->getOpcode() == BinaryOperator::PtrMemI) {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(BO->getType());
- QualType ResultTy = FPT->getResultType().getNonReferenceType();
+ if (const FunctionProtoType *FPT =
+ dyn_cast<FunctionProtoType>(BO->getType())) {
+ QualType ResultTy = FPT->getResultType().getNonReferenceType();
- ExprOwningPtr<CXXMemberCallExpr>
- TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
- NumArgs, ResultTy,
- RParenLoc));
+ ExprOwningPtr<CXXMemberCallExpr>
+ TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
+ NumArgs, ResultTy,
+ RParenLoc));
- if (CheckCallReturnType(FPT->getResultType(),
- BO->getRHS()->getSourceRange().getBegin(),
- TheCall.get(), 0))
- return ExprError();
+ if (CheckCallReturnType(FPT->getResultType(),
+ BO->getRHS()->getSourceRange().getBegin(),
+ TheCall.get(), 0))
+ return ExprError();
- if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
- RParenLoc))
- return ExprError();
+ if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
+ RParenLoc))
+ return ExprError();
- return Owned(MaybeBindToTemporary(TheCall.release()).release());
+ return Owned(MaybeBindToTemporary(TheCall.release()).release());
+ }
+ return ExprError(Diag(Fn->getLocStart(),
+ diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
}
}
}
@@ -2893,7 +2865,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
// lookup and whether there were any explicitly-specified template arguments.
bool ADL = true;
bool HasExplicitTemplateArgs = 0;
- const TemplateArgument *ExplicitTemplateArgs = 0;
+ const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -2932,19 +2904,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
if (!FDecl)
return ExprError();
- // Update Fn to refer to the actual function selected.
- Expr *NewFn = 0;
- if (Qualifier)
- NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart(),
- false, false,
- QualifierRange,
- Qualifier);
- else
- NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart());
- Fn->Destroy(Context);
- Fn = NewFn;
+ Fn = FixOverloadedFunctionReference(Fn, FDecl);
}
}
@@ -3543,7 +3503,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
compositeType = Context.getObjCIdType();
} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
- } else {
+ } else if (!(compositeType =
+ Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
+ ;
+ else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
<< LHS->getSourceRange() << RHS->getSourceRange();
@@ -4080,7 +4043,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
- // DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
+ // DeclExpr's (created by ActOnIdExpression), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.
@@ -4428,6 +4391,10 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
return InvalidOperands(Loc, lex, rex);
+ // Vector shifts promote their scalar inputs to vector type.
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(Loc, lex, rex);
+
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
QualType LHSTy = Context.isPromotableBitField(lex);
@@ -5083,7 +5050,6 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
static NamedDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
case Stmt::MemberExprClass:
// If this is an arrow operator, the address is an offset from
@@ -5199,7 +5165,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
// scope qualifier for the class.
- if (isa<QualifiedDeclRefExpr>(op)) {
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (FD->getType()->isReferenceType()) {
@@ -5216,7 +5182,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) {
// Okay: we can take the address of a function.
// As above.
- if (isa<QualifiedDeclRefExpr>(op) && MD->isInstance())
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+ MD->isInstance())
return Context.getMemberPointerType(op->getType(),
Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (!isa<FunctionDecl>(dcl))
@@ -5426,6 +5393,72 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
OpLoc));
}
+/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps
+/// ParenRange in parentheses.
+static void SuggestParentheses(Sema &Self, SourceLocation Loc,
+ const PartialDiagnostic &PD,
+ SourceRange ParenRange)
+{
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+ if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just dig the
+ // warning/error and return.
+ Self.Diag(Loc, PD);
+ return;
+ }
+
+ Self.Diag(Loc, PD)
+ << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
+ << CodeModificationHint::CreateInsertion(EndLoc, ")");
+}
+
+/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
+/// operators are mixed in a way that suggests that the programmer forgot that
+/// comparison operators have higher precedence. The most typical example of
+/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+ SourceLocation OpLoc,Expr *lhs,Expr *rhs){
+ typedef BinaryOperator BinOp;
+ BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1),
+ rhsopc = static_cast<BinOp::Opcode>(-1);
+ if (BinOp *BO = dyn_cast<BinOp>(lhs))
+ lhsopc = BO->getOpcode();
+ if (BinOp *BO = dyn_cast<BinOp>(rhs))
+ rhsopc = BO->getOpcode();
+
+ // Subs are not binary operators.
+ if (lhsopc == -1 && rhsopc == -1)
+ return;
+
+ // Bitwise operations are sometimes used as eager logical ops.
+ // Don't diagnose this.
+ if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) &&
+ (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc)))
+ return;
+
+ if (BinOp::isComparisonOp(lhsopc))
+ SuggestParentheses(Self, OpLoc,
+ PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(lhs->getLocStart(), OpLoc)
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
+ SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
+ else if (BinOp::isComparisonOp(rhsopc))
+ SuggestParentheses(Self, OpLoc,
+ PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(OpLoc, rhs->getLocEnd())
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
+ SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
+}
+
+/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
+/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3".
+/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does.
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+ SourceLocation OpLoc, Expr *lhs, Expr *rhs){
+ if (BinaryOperator::isBitwiseOp(Opc))
+ DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs);
+}
+
// Binary Operators. 'Tok' is the token for the operator.
Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
@@ -5436,6 +5469,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
+ // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
+ DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
@@ -5451,7 +5487,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
Expr *Args[2] = { lhs, rhs };
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, Args, 2, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
}
// Build the (potentially-overloaded, potentially-dependent)
@@ -5569,7 +5605,7 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
Functions);
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, &Input, 1, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
}
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
@@ -5673,6 +5709,10 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (!Dependent) {
bool DidWarnAboutNonPOD = false;
+ if (RequireCompleteType(TypeLoc, Res->getType(),
+ diag::err_offsetof_incomplete_type))
+ return ExprError();
+
// FIXME: Dependent case loses a lot of information here. And probably
// leaks like a sieve.
for (unsigned i = 0; i != NumComponents; ++i) {
@@ -6240,21 +6280,21 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Implicit instantiation of function templates and member functions of
// class templates.
- if (!Function->getBody() &&
- Function->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
+ if (!Function->getBody() && Function->isImplicitlyInstantiable()) {
bool AlreadyInstantiated = false;
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
if (SpecInfo->getPointOfInstantiation().isInvalid())
SpecInfo->setPointOfInstantiation(Loc);
- else
+ else if (SpecInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
AlreadyInstantiated = true;
} else if (MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo()) {
if (MSInfo->getPointOfInstantiation().isInvalid())
MSInfo->setPointOfInstantiation(Loc);
- else
+ else if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
AlreadyInstantiated = true;
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d4d031f91ed5..4868c14835f4 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -22,41 +22,6 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
-/// name (e.g., operator void const *) as an expression. This is
-/// very similar to ActOnIdentifierExpr, except that instead of
-/// providing an identifier the parser provides the type of the
-/// conversion function.
-Sema::OwningExprResult
-Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc,
- TypeTy *Ty, bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand) {
- //FIXME: Preserve type source info.
- QualType ConvType = GetTypeFromParser(Ty);
- CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
- DeclarationName ConvName
- = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
- return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen,
- &SS, isAddressOfOperand);
-}
-
-/// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator
-/// name (e.g., @c operator+ ) as an expression. This is very
-/// similar to ActOnIdentifierExpr, except that instead of providing
-/// an identifier the parser provides the kind of overloaded
-/// operator that was parsed.
-Sema::OwningExprResult
-Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand) {
- DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
- return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS,
- isAddressOfOperand);
-}
-
/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
Action::OwningExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
@@ -212,7 +177,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
PDiag(diag::err_invalid_incomplete_type_use)
<< FullRange))
return ExprError();
-
+
if (RequireNonAbstractType(TyBeginLoc, Ty,
diag::err_allocation_of_abstract_type))
return ExprError();
@@ -288,7 +253,6 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
<< FullRange);
assert(NumExprs == 0 && "Expected 0 expressions");
-
// C++ [expr.type.conv]p2:
// The expression T(), where T is a simple-type-specifier for a non-array
// complete object type or the (possibly cv-qualified) void type, creates an
@@ -312,7 +276,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen) {
Expr *ArraySize = 0;
- unsigned Skip = 0;
// If the specified type is an array, unwrap it and save the expression.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
@@ -323,14 +286,25 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (!Chunk.Arr.NumElts)
return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
<< D.getSourceRange());
+
+ if (ParenTypeId) {
+ // Can't have dynamic array size when the type-id is in parentheses.
+ Expr *NumElts = (Expr *)Chunk.Arr.NumElts;
+ if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
+ !NumElts->isIntegerConstantExpr(Context)) {
+ Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst)
+ << NumElts->getSourceRange();
+ return ExprError();
+ }
+ }
+
ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
- Skip = 1;
+ D.DropFirstTypeObject();
}
// Every dimension shall be of constant size.
- if (D.getNumTypeObjects() > 0 &&
- D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
- for (unsigned I = 1, N = D.getNumTypeObjects(); I < N; ++I) {
+ if (ArraySize) {
+ for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
break;
@@ -345,10 +319,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
}
}
-
+
//FIXME: Store DeclaratorInfo in CXXNew expression.
DeclaratorInfo *DInfo = 0;
- QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo, Skip);
+ QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo);
if (D.isInvalidType())
return ExprError();
@@ -935,7 +909,7 @@ Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc,
// FIXME: Store DeclaratorInfo in the expression.
DeclaratorInfo *DInfo = 0;
TagDecl *OwnedTag = 0;
- QualType Ty = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, &OwnedTag);
+ QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag);
if (Ty->isFunctionType()) { // The declarator shall not specify a function...
// We exit without creating a CXXConditionDeclExpr because a FunctionDecl
@@ -1139,6 +1113,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
From = CastArg.takeAs<Expr>();
return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor);
}
+
+ if (ICS.UserDefined.After.Second == ICK_Pointer_Member &&
+ ToType.getNonReferenceType()->isMemberFunctionPointerType())
+ CastKind = CastExpr::CK_BaseToDerivedMemberPointer;
From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
CastKind, CastArg.takeAs<Expr>(),
@@ -1390,7 +1368,8 @@ QualType Sema::CheckPointerToMemberOperands(
LType = Ptr->getPointeeType().getNonReferenceType();
else {
Diag(Loc, diag::err_bad_memptr_lhs)
- << OpSpelling << 1 << LType << lex->getSourceRange();
+ << OpSpelling << 1 << LType
+ << CodeModificationHint::CreateReplacement(SourceRange(Loc), ".*");
return QualType();
}
}
@@ -1403,8 +1382,10 @@ QualType Sema::CheckPointerToMemberOperands(
// overkill?
if (!IsDerivedFrom(LType, Class, Paths) ||
Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+ const char *ReplaceStr = isIndirect ? ".*" : "->*";
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
- << (int)isIndirect << lex->getType() << lex->getSourceRange();
+ << (int)isIndirect << lex->getType() <<
+ CodeModificationHint::CreateReplacement(SourceRange(Loc), ReplaceStr);
return QualType();
}
}
@@ -2105,110 +2086,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
return move(Base);
}
-Sema::OwningExprResult
-Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- if (SS.isInvalid())
- return ExprError();
-
- QualType BaseType;
- if (isUnknownSpecialization(SS))
- BaseType = Context.getTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
- ClassName);
- else {
- TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
-
- // FIXME: If Base is dependent, we might not be able to resolve it here.
- if (!BaseTy) {
- Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << ClassName;
- return ExprError();
- }
-
- BaseType = GetTypeFromParser(BaseTy);
- }
-
- return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
- SourceRange(ClassNameLoc),
- BaseType.getAsOpaquePtr(),
- SS, HasTrailingLParen);
-}
-
-Sema::OwningExprResult
-Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *T,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- QualType Type = QualType::getFromOpaquePtr(T);
- CanQualType CanType = Context.getCanonicalType(Type);
- DeclarationName DtorName =
- Context.DeclarationNames.getCXXDestructorName(CanType);
-
- OwningExprResult Result
- = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
- TypeRange.getBegin(), DtorName, DeclPtrTy(),
- &SS);
- if (Result.isInvalid() || HasTrailingLParen)
- return move(Result);
-
- // The only way a reference to a destructor can be used is to
- // immediately call them. Since the next token is not a '(', produce a
- // diagnostic and build the call now.
- Expr *E = (Expr *)Result.get();
- SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
- Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
- << isa<CXXPseudoDestructorExpr>(E)
- << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-
- return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
- MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
-}
-
-Sema::OwningExprResult
-Sema::ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS) {
- if (SS && SS->isInvalid())
- return ExprError();
-
- DeclarationName Name =
- Context.DeclarationNames.getCXXOperatorName(OverOpKind);
-
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- Name, DeclPtrTy(), SS);
-}
-
-Sema::OwningExprResult
-Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS) {
- if (SS && SS->isInvalid())
- return ExprError();
-
- //FIXME: Preserve type source info.
- QualType ConvType = GetTypeFromParser(Ty);
- CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
- DeclarationName ConvName =
- Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
-
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- ConvName, DeclPtrTy(), SS);
-}
-
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
CXXMethodDecl *Method) {
MemberExpr *ME =
@@ -2333,6 +2210,7 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ // FIXME: Do we have to know if there are explicit template arguments?
if (Method && !Method->isStatic()) {
Ctx = Method->getParent();
if (isa<CXXMethodDecl>(D) && !FunTmpl)
@@ -2350,6 +2228,12 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
// Determine whether the declaration(s) we found are actually in a base
// class. If not, this isn't an implicit member reference.
ThisType = MD->getThisType(Context);
+
+ // If the type of "this" is dependent, we can't tell if the member is in a
+ // base class or not, so treat this as a dependent implicit member reference.
+ if (ThisType->isDependentType())
+ return true;
+
QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
QualType ClassType
= Context.getTypeDeclType(cast<CXXRecordDecl>(MD->getParent()));
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index dd877c16fba7..93752e130c94 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1239,6 +1239,14 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
BaseEnd = Class->bases_end();
Base != BaseEnd; ++Base) {
const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+ // In dependent contexts, we do ADL twice, and the first time around,
+ // the base type might be a dependent TemplateSpecializationType, or a
+ // TemplateTypeParmType. If that happens, simply ignore it.
+ // FIXME: If we want to support export, we probably need to add the
+ // namespace of the template in a TemplateSpecializationType, or even
+ // the classes and namespaces of known non-dependent arguments.
+ if (!BaseType)
+ continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (AssociatedClasses.insert(BaseDecl)) {
// Find the associated namespace for this base class.
@@ -1561,7 +1569,7 @@ static void CollectFunctionDecl(Sema::FunctionSet &Functions,
Functions.insert(FunTmpl);
}
-void Sema::ArgumentDependentLookup(DeclarationName Name,
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions) {
// Find all of the associated namespaces and classes based on the
@@ -1572,6 +1580,13 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
AssociatedNamespaces,
AssociatedClasses);
+ QualType T1, T2;
+ if (Operator) {
+ T1 = Args[0]->getType();
+ if (NumArgs >= 2)
+ T2 = Args[1]->getType();
+ }
+
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
@@ -1608,7 +1623,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
continue;
}
- CollectFunctionDecl(Functions, D);
+ FunctionDecl *Fn;
+ if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
+ IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
+ CollectFunctionDecl(Functions, D);
}
}
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index ebcf3ad8e2bc..946e28269eb6 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -999,6 +999,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
// here. That is handled by CheckPointerConversion.
if (getLangOptions().CPlusPlus &&
FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+ !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
IsDerivedFrom(FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
@@ -2444,7 +2445,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2489,7 +2490,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2761,7 +2762,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
if (S)
LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
- ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions);
AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
@@ -3119,9 +3120,8 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
}
}
-/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers
-/// , if any, found in visible type conversion functions found in ArgExpr's
-/// type.
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers,
+/// if any, found in visible type conversion functions found in ArgExpr's type.
static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
Qualifiers VRQuals;
const RecordType *TyRec;
@@ -3139,7 +3139,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
OverloadedFunctionDecl *Conversions =
- ClassDecl->getVisibleConversionFunctions();
+ ClassDecl->getVisibleConversionFunctions();
for (OverloadedFunctionDecl::function_iterator Func
= Conversions->function_begin();
@@ -3887,7 +3887,7 @@ void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
Expr **Args, unsigned NumArgs,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
@@ -3908,7 +3908,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
}
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Args, NumArgs, Functions);
+ ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions);
// Erase all of the candidates we already knew about.
// FIXME: This is suboptimal. Is there a better way?
@@ -4279,7 +4279,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
}
bool HasExplicitTemplateArgs = false;
- const TemplateArgument *ExplicitTemplateArgs = 0;
+ const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
// Try to dig out the overloaded function.
@@ -4287,10 +4287,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
+ HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
+ ExplicitTemplateArgs = DR->getTemplateArgs();
+ NumExplicitTemplateArgs = DR->getNumTemplateArgs();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
- // FIXME: Explicit template arguments
+ HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
+ ExplicitTemplateArgs = ME->getTemplateArgs();
+ NumExplicitTemplateArgs = ME->getNumTemplateArgs();
} else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
TemplateName Name = TIRE->getTemplateName();
Ovl = Name.getAsOverloadedFunctionDecl();
@@ -4367,6 +4372,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// when converting to member pointer.
if (Method->isStatic() == IsMember)
continue;
+
+ // If we have explicit template arguments, skip non-templates.
+ if (HasExplicitTemplateArgs)
+ continue;
} else if (IsMember)
continue;
@@ -4443,7 +4452,7 @@ static void AddOverloadedCallCandidate(Sema &S,
AnyFunctionDecl Callee,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -4475,7 +4484,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee,
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -4543,7 +4552,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee,
FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -4934,6 +4943,134 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
+Action::OwningExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base, ExprArg Idx) {
+ Expr *Args[2] = { static_cast<Expr*>(Base.get()),
+ static_cast<Expr*>(Idx.get()) };
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+ // If either side is type-dependent, create an appropriate dependent
+ // expression.
+ if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+ OverloadedFunctionDecl *Overloads
+ = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+
+ DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
+ LLoc, false, false);
+
+ Base.release();
+ Idx.release();
+ return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+ Args, 2,
+ Context.DependentTy,
+ RLoc));
+ }
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet;
+
+ // Subscript can only be overloaded as a member function.
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (BestViableFunction(CandidateSet, LLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ // Convert the arguments.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+ if (PerformObjectArgumentInitialization(Args[0], Method) ||
+ PerformCopyInitialization(Args[1],
+ FnDecl->getParamDecl(0)->getType(),
+ "passing"))
+ return ExprError();
+
+ // Determine the result type
+ QualType ResultTy
+ = FnDecl->getType()->getAs<FunctionType>()->getResultType();
+ ResultTy = ResultTy.getNonReferenceType();
+
+ // Build the actual expression node.
+ Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+ LLoc);
+ UsualUnaryConversions(FnExpr);
+
+ Base.release();
+ Idx.release();
+ ExprOwningPtr<CXXOperatorCallExpr>
+ TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+ FnExpr, Args, 2,
+ ResultTy, RLoc));
+
+ if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall.release());
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], "passing") ||
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], "passing"))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function: {
+ // No viable function; try to create a built-in operation, which will
+ // produce an error. Then, show the non-viable candidates.
+ OwningExprResult Result =
+ CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+ assert(Result.isInvalid() &&
+ "C++ subscript operator overloading is missing candidates!");
+ if (Result.isInvalid())
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ "[]", LLoc);
+ return move(Result);
+ }
+
+ case OR_Ambiguous:
+ Diag(LLoc, diag::err_ovl_ambiguous_oper)
+ << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ "[]", LLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(LLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted() << "[]"
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ return ExprError();
+ }
+
+ // We matched a built-in operator; build it.
+ Base.release();
+ Idx.release();
+ return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc,
+ Owned(Args[1]), RLoc);
+}
+
/// BuildCallToMemberFunction - Build a call to a member
/// function. MemExpr is the expression that refers to the member
/// function (and includes the object parameter), Args/NumArgs are the
@@ -4967,10 +5104,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
Func != FuncEnd; ++Func) {
- if ((Method = dyn_cast<CXXMethodDecl>(*Func)))
+ if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
+ // If explicit template arguments were provided, we can't call a
+ // non-template member function.
+ if (MemExpr->hasExplicitTemplateArgumentList())
+ continue;
+
AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/false);
- else
+ } else
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
MemExpr->hasExplicitTemplateArgumentList(),
MemExpr->getTemplateArgs(),
@@ -5361,8 +5503,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
- NewExpr->setType(PE->getSubExpr()->getType());
- return NewExpr;
+ PE->setSubExpr(NewExpr);
+ PE->setType(NewExpr->getType());
+ } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+ assert(Context.hasSameType(ICE->getSubExpr()->getType(),
+ NewExpr->getType()) &&
+ "Implicit cast type cannot be determined from overload");
+ ICE->setSubExpr(NewExpr);
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
"Can only take the address of an overloaded function");
@@ -5370,18 +5518,19 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
if (Method->isStatic()) {
// Do nothing: static member functions aren't any different
// from non-member functions.
- } else if (QualifiedDeclRefExpr *DRE
- = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr())) {
- // We have taken the address of a pointer to member
- // function. Perform the computation here so that we get the
- // appropriate pointer to member type.
- DRE->setDecl(Fn);
- DRE->setType(Fn->getType());
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- E->setType(Context.getMemberPointerType(Fn->getType(),
- ClassType.getTypePtr()));
- return E;
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) {
+ if (DRE->getQualifier()) {
+ // We have taken the address of a pointer to member
+ // function. Perform the computation here so that we get the
+ // appropriate pointer to member type.
+ DRE->setDecl(Fn);
+ DRE->setType(Fn->getType());
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ E->setType(Context.getMemberPointerType(Fn->getType(),
+ ClassType.getTypePtr()));
+ return E;
+ }
}
// FIXME: TemplateIdRefExpr referring to a member function template
// specialization!
@@ -5393,26 +5542,35 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
return UnOp;
} else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
- isa<FunctionTemplateDecl>(DR->getDecl())) &&
- "Expected overloaded function or function template");
+ isa<FunctionTemplateDecl>(DR->getDecl()) ||
+ isa<FunctionDecl>(DR->getDecl())) &&
+ "Expected function or function template");
DR->setDecl(Fn);
E->setType(Fn->getType());
} else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
MemExpr->setMemberDecl(Fn);
E->setType(Fn->getType());
} else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
- // FIXME: We should capture the template arguments here.
- if (NestedNameSpecifier *Qualifier = TID->getQualifier())
- E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc(),
- /*FIXME?*/false, /*FIXME?*/false,
- TID->getQualifierRange(),
- Qualifier);
- else
- E = new (Context) DeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc());
+ E = DeclRefExpr::Create(Context,
+ TID->getQualifier(), TID->getQualifierRange(),
+ Fn, TID->getTemplateNameLoc(),
+ true,
+ TID->getLAngleLoc(),
+ TID->getTemplateArgs(),
+ TID->getNumTemplateArgs(),
+ TID->getRAngleLoc(),
+ Fn->getType(),
+ /*FIXME?*/false, /*FIXME?*/false);
- TID->Destroy(Context);
+ // FIXME: Don't destroy TID here, since we need its template arguments
+ // to survive.
+ // TID->Destroy(Context);
+ } else if (isa<UnresolvedFunctionNameExpr>(E)) {
+ return DeclRefExpr::Create(Context,
+ /*Qualifier=*/0,
+ /*QualifierRange=*/SourceRange(),
+ Fn, E->getLocStart(),
+ Fn->getType(), false, false);
} else {
assert(false && "Invalid reference to overloaded function");
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 145342438503..6a65bd1dd1ec 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -70,7 +70,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
SourceLocation Loc;
SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(Loc, R1, R2))
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
return;
// Okay, we have an unused result. Depending on what the base expression is,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 0f223208a938..3c56358d5a94 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -98,29 +98,43 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) {
}
TemplateNameKind Sema::isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult) {
+ DeclarationName TName;
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ TName = DeclarationName(Name.Identifier);
+ break;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ TName = Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator);
+ break;
+
+ default:
+ return TNK_Non_template;
+ }
+
// Determine where to perform name lookup
DeclContext *LookupCtx = 0;
bool isDependent = false;
if (ObjectTypePtr) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
- assert((!SS || !SS->isSet()) &&
- "ObjectType and scope specifier cannot coexist");
+ assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
- } else if (SS && SS->isSet()) {
+ } else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
- LookupCtx = computeDeclContext(*SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(*SS);
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(SS);
}
LookupResult Found;
@@ -132,10 +146,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// nested-name-specifier.
// The declaration context must be complete.
- if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
+ if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
return TNK_Non_template;
- LookupQualifiedName(Found, LookupCtx, &II, LookupOrdinaryName);
+ LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName);
if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) {
// C++ [basic.lookup.classref]p1:
@@ -150,7 +164,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
//
// FIXME: When we're instantiating a template, do we actually have to
// look in the scope of the template? Seems fishy...
- LookupName(Found, S, &II, LookupOrdinaryName);
+ LookupName(Found, S, TName, LookupOrdinaryName);
ObjectTypeSearchedInScope = true;
}
} else if (isDependent) {
@@ -158,7 +172,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
return TNK_Non_template;
} else {
// Perform unqualified name lookup in the current scope.
- LookupName(Found, S, &II, LookupOrdinaryName);
+ LookupName(Found, S, TName, LookupOrdinaryName);
}
// FIXME: Cope with ambiguous name-lookup results.
@@ -177,7 +191,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// postfix-expression and [...]
//
LookupResult FoundOuter;
- LookupName(FoundOuter, S, &II, LookupOrdinaryName);
+ LookupName(FoundOuter, S, TName, LookupOrdinaryName);
// FIXME: Handle ambiguities in this lookup better
NamedDecl *OuterTemplate
= isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
@@ -194,8 +208,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// entity as the one found in the class of the object expression,
// otherwise the program is ill-formed.
if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) {
- Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
- << &II;
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_nested_name_member_ref_lookup_ambiguous)
+ << TName
+ << Name.getSourceRange();
Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type)
<< QualType::getFromOpaquePtr(ObjectTypePtr);
Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope);
@@ -206,9 +222,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
}
}
- if (SS && SS->isSet() && !SS->isInvalid()) {
+ if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(Template))
TemplateResult
@@ -321,8 +337,11 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
TypeTy *DefaultT) {
TemplateTypeParmDecl *Parm
= cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
- // FIXME: Preserve type source info.
- QualType Default = GetTypeFromParser(DefaultT);
+
+ DeclaratorInfo *DefaultDInfo;
+ GetTypeFromParser(DefaultT, &DefaultDInfo);
+
+ assert(DefaultDInfo && "expected source information for type");
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
@@ -337,12 +356,12 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
// FIXME: Implement this check! Needs a recursive walk over the types.
// Check the template argument itself.
- if (CheckTemplateArgument(Parm, Default, DefaultLoc)) {
+ if (CheckTemplateArgument(Parm, DefaultDInfo)) {
Parm->setInvalidDecl();
return;
}
- Parm->setDefaultArgument(Default, DefaultLoc, false);
+ Parm->setDefaultArgument(DefaultDInfo, false);
}
/// \brief Check that the type of a non-type template parameter is
@@ -610,11 +629,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SemanticContext = PrevDecl->getDeclContext();
} else {
// Declarations in outer scopes don't matter. However, the outermost
- // context we computed is the semntic context for our new
+ // context we computed is the semantic context for our new
// declaration.
PrevDecl = 0;
SemanticContext = OutermostContext;
}
+
+ if (CurContext->isDependentContext()) {
+ // If this is a dependent context, we don't want to link the friend
+ // class template to the template in scope, because that would perform
+ // checking of the template parameter lists that can't be performed
+ // until the outer context is instantiated.
+ PrevDecl = 0;
+ }
} else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
PrevDecl = 0;
@@ -843,7 +870,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
SawParameterPack = true;
ParameterPackLoc = NewTypeParm->getLocation();
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
- NewTypeParm->hasDefaultArgument()) {
+ NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
@@ -853,8 +880,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge the default argument from the old declaration to the
// new declaration.
SawDefaultArgument = true;
- NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgument(),
- OldTypeParm->getDefaultArgumentLoc(),
+ NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
true);
PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
} else if (NewTypeParm->hasDefaultArgument()) {
@@ -1096,24 +1122,28 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
SourceLocation *TemplateArgLocs,
- llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) {
+ llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) {
TemplateArgs.reserve(TemplateArgsIn.size());
void **Args = TemplateArgsIn.getArgs();
bool *ArgIsType = TemplateArgsIn.getArgIsType();
for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
- TemplateArgs.push_back(
- ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg],
- //FIXME: Preserve type source info.
- Sema::GetTypeFromParser(Args[Arg]))
- : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg])));
+ if (ArgIsType[Arg]) {
+ DeclaratorInfo *DI;
+ QualType T = Sema::GetTypeFromParser(Args[Arg], &DI);
+ if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]);
+ TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
+ } else {
+ Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
+ TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
+ }
}
}
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
TemplateDecl *Template = Name.getAsTemplateDecl();
@@ -1155,7 +1185,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Converted.flatSize());
// FIXME: CanonType is not actually the canonical type, and unfortunately
- // it is a TemplateTypeSpecializationType that we will never use again.
+ // it is a TemplateSpecializationType that we will never use again.
// In the future, we need to teach getTemplateSpecializationType to only
// build the canonical type and return that to us.
CanonType = Context.getCanonicalType(CanonType);
@@ -1190,7 +1220,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- //FIXME: Preserve type source info.
return Context.getTemplateSpecializationType(Name, TemplateArgs,
NumTemplateArgs, CanonType);
}
@@ -1199,13 +1228,13 @@ Action::TypeResult
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
+ SourceLocation *TemplateArgLocsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs);
QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
TemplateArgs.data(),
@@ -1216,7 +1245,16 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
if (Result.isNull())
return true;
- return Result.getAsOpaquePtr();
+ DeclaratorInfo *DI = Context.CreateDeclaratorInfo(Result);
+ TemplateSpecializationTypeLoc TL
+ = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TL.setTemplateNameLoc(TemplateLoc);
+ TL.setLAngleLoc(LAngleLoc);
+ TL.setRAngleLoc(RAngleLoc);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+ return CreateLocInfoType(Result, DI).getAsOpaquePtr();
}
Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
@@ -1226,7 +1264,9 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
if (TypeResult.isInvalid())
return Sema::TypeResult();
- QualType Type = QualType::getFromOpaquePtr(TypeResult.get());
+ // FIXME: preserve source info, ideally without copying the DI.
+ DeclaratorInfo *DI;
+ QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
// Verify the tag specifier.
TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
@@ -1256,7 +1296,7 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
// FIXME: Can we do any checking at this point? I guess we could check the
@@ -1296,13 +1336,13 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
+ SourceLocation *TemplateArgSLs,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs);
TemplateArgsIn.release();
return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
@@ -1312,41 +1352,6 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
RAngleLoc);
}
-Sema::OwningExprResult
-Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- TemplateName Template = TemplateD.getAsVal<TemplateName>();
-
- // FIXME: We're going to end up looking up the template based on its name,
- // twice!
- DeclarationName Name;
- if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
- Name = ActualTemplate->getDeclName();
- else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
- Name = Ovl->getDeclName();
- else
- Name = Template.getAsDependentTemplateName()->getName();
-
- // Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
- TemplateArgsIn.release();
-
- // Do we have the save the actual template name? We might need it...
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc,
- Name, true, LAngleLoc,
- TemplateArgs.data(), TemplateArgs.size(),
- RAngleLoc, DeclPtrTy(), &SS);
-}
-
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
@@ -1356,9 +1361,8 @@ Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
/// of the "template" keyword, and "apply" is the \p Name.
Sema::TemplateTy
Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType) {
if ((ObjectType &&
computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
@@ -1380,11 +1384,13 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode, retroactively applying the DR.
TemplateTy Template;
- TemplateNameKind TNK = isTemplateName(0, Name, NameLoc, &SS, ObjectType,
+ TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
false, Template);
if (TNK == TNK_Non_template) {
- Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
- << &Name;
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name)
+ << Name.getSourceRange();
return TemplateTy();
}
@@ -1393,12 +1399,32 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
NestedNameSpecifier *Qualifier
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name));
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.Identifier));
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.OperatorFunctionId.Operator));
+
+ default:
+ break;
+ }
+
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name)
+ << Name.getSourceRange();
+ return TemplateTy();
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgument &Arg,
+ const TemplateArgumentLoc &AL,
TemplateArgumentListBuilder &Converted) {
+ const TemplateArgument &Arg = AL.getArgument();
+
// Check template type parameter.
if (Arg.getKind() != TemplateArgument::Type) {
// C++ [temp.arg.type]p1:
@@ -1407,19 +1433,19 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
// We have a template type parameter but the template argument
// is not a type.
- Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
+ SourceRange SR = AL.getSourceRange();
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
- if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation()))
+ if (CheckTemplateArgument(Param, AL.getSourceDeclaratorInfo()))
return true;
// Add the converted template type argument.
Converted.Append(
- TemplateArgument(Arg.getLocation(),
- Context.getCanonicalType(Arg.getAsType())));
+ TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
return false;
}
@@ -1428,7 +1454,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc,
bool PartialTemplateArgs,
@@ -1474,7 +1500,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
// Decode the template argument
- TemplateArgument Arg;
+ TemplateArgumentLoc Arg;
+
if (ArgIdx >= NumArgs) {
// Retrieve the default template argument from the template
// parameter.
@@ -1489,11 +1516,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!TTP->hasDefaultArgument())
break;
- QualType ArgType = TTP->getDefaultArgument();
+ DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo();
// If the argument type is dependent, instantiate it now based
// on the previously-computed template arguments.
- if (ArgType->isDependentType()) {
+ if (ArgType->getType()->isDependentType()) {
InstantiatingTemplate Inst(*this, TemplateLoc,
Template, Converted.getFlatArguments(),
Converted.flatSize(),
@@ -1507,10 +1534,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
TTP->getDeclName());
}
- if (ArgType.isNull())
+ if (!ArgType)
return true;
- Arg = TemplateArgument(TTP->getLocation(), ArgType);
+ Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType);
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
if (!NTTP->hasDefaultArgument())
@@ -1530,7 +1557,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (E.isInvalid())
return true;
- Arg = TemplateArgument(E.takeAs<Expr>());
+ Expr *Ex = E.takeAs<Expr>();
+ Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
} else {
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
@@ -1539,7 +1567,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
// FIXME: Subst default argument
- Arg = TemplateArgument(TempParm->getDefaultArgument());
+ Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()),
+ TempParm->getDefaultArgument());
}
} else {
// Retrieve the template argument produced by the user.
@@ -1592,13 +1621,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
}
}
- switch (Arg.getKind()) {
+ switch (Arg.getArgument().getKind()) {
case TemplateArgument::Null:
assert(false && "Should never see a NULL template argument here");
break;
case TemplateArgument::Expression: {
- Expr *E = Arg.getAsExpr();
+ Expr *E = Arg.getArgument().getAsExpr();
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
Invalid = true;
@@ -1611,10 +1640,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Integral:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
- Converted.Append(Arg);
+ Converted.Append(Arg.getArgument());
break;
- case TemplateArgument::Type:
+ case TemplateArgument::Type: {
// We have a non-type template parameter but the template
// argument is a type.
@@ -1625,14 +1654,17 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
//
// We warn specifically about this case, since it can be rather
// confusing for users.
- if (Arg.getAsType()->isFunctionType())
- Diag(Arg.getLocation(), diag::err_template_arg_nontype_ambig)
- << Arg.getAsType();
+ QualType T = Arg.getArgument().getAsType();
+ SourceRange SR = Arg.getSourceRange();
+ if (T->isFunctionType())
+ Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig)
+ << SR << T;
else
- Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr);
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
Diag((*Param)->getLocation(), diag::note_template_param_here);
Invalid = true;
break;
+ }
case TemplateArgument::Pack:
assert(0 && "FIXME: Implement!");
@@ -1643,13 +1675,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
- switch (Arg.getKind()) {
+ switch (Arg.getArgument().getKind()) {
case TemplateArgument::Null:
assert(false && "Should never see a NULL template argument here");
break;
case TemplateArgument::Expression: {
- Expr *ArgExpr = Arg.getAsExpr();
+ Expr *ArgExpr = Arg.getArgument().getAsExpr();
if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
@@ -1658,7 +1690,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Add the converted template argument.
Decl *D
= cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl();
- Converted.Append(TemplateArgument(Arg.getLocation(), D));
+ Converted.Append(TemplateArgument(D));
continue;
}
}
@@ -1675,7 +1707,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Declaration:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
- Converted.Append(Arg);
+ Converted.Append(Arg.getArgument());
break;
case TemplateArgument::Integral:
@@ -1698,7 +1730,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
/// This routine implements the semantics of C++ [temp.arg.type]. It
/// returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
- QualType Arg, SourceLocation ArgLoc) {
+ DeclaratorInfo *ArgInfo) {
+ assert(ArgInfo && "invalid DeclaratorInfo");
+ QualType Arg = ArgInfo->getType();
+
// C++ [temp.arg.type]p2:
// A local type, a type with no linkage, an unnamed type or a type
// compounded from any of these types shall not be used as a
@@ -1710,12 +1745,14 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
Tag = EnumT;
else if (const RecordType *RecordT = Arg->getAs<RecordType>())
Tag = RecordT;
- if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod())
- return Diag(ArgLoc, diag::err_template_arg_local_type)
- << QualType(Tag, 0);
- else if (Tag && !Tag->getDecl()->getDeclName() &&
+ if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+ SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+ return Diag(SR.getBegin(), diag::err_template_arg_local_type)
+ << QualType(Tag, 0) << SR;
+ } else if (Tag && !Tag->getDecl()->getDeclName() &&
!Tag->getDecl()->getTypedefForAnonDecl()) {
- Diag(ArgLoc, diag::err_template_arg_unnamed_type);
+ SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+ Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
return true;
}
@@ -1845,7 +1882,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
// template-parameter shall be one of: [...]
//
// -- a pointer to member expressed as described in 5.3.1.
- QualifiedDeclRefExpr *DRE = 0;
+ DeclRefExpr *DRE = 0;
// Ignore (and complain about) any excess parentheses.
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
@@ -1860,8 +1897,11 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg))
- if (UnOp->getOpcode() == UnaryOperator::AddrOf)
- DRE = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr());
+ if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
+ DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+ if (DRE && !DRE->getQualifier())
+ DRE = 0;
+ }
if (!DRE)
return Diag(Arg->getSourceRange().getBegin(),
@@ -2012,7 +2052,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return false;
}
- Converted = TemplateArgument(StartLoc, Value,
+ Converted = TemplateArgument(Value,
ParamType->isEnumeralType() ? ParamType
: IntegerType);
return false;
@@ -2086,7 +2126,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Member)
Member = cast<NamedDecl>(Member->getCanonicalDecl());
- Converted = TemplateArgument(StartLoc, Member);
+ Converted = TemplateArgument(Member);
return false;
}
@@ -2096,7 +2136,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Entity)
Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(StartLoc, Entity);
+ Converted = TemplateArgument(Entity);
return false;
}
@@ -2136,7 +2176,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Entity)
Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(StartLoc, Entity);
+ Converted = TemplateArgument(Entity);
return false;
}
@@ -2177,7 +2217,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return true;
Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(StartLoc, Entity);
+ Converted = TemplateArgument(Entity);
return false;
}
@@ -2207,7 +2247,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Member)
Member = cast<NamedDecl>(Member->getCanonicalDecl());
- Converted = TemplateArgument(StartLoc, Member);
+ Converted = TemplateArgument(Member);
return false;
}
@@ -2719,7 +2759,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
if (TTP->hasDefaultArgument()) {
Diag(TTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec);
- TTP->setDefaultArgument(QualType(), SourceLocation(), false);
+ TTP->removeDefaultArgument();
}
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
@@ -2778,7 +2818,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
// Check that the template argument list is well-formed for this
@@ -2877,8 +2917,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted.flatSize());
// Create a new class template partial specialization declaration node.
- TemplateParameterList *TemplateParams
- = static_cast<TemplateParameterList*>(*TemplateParameterLists.get());
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
ClassTemplatePartialSpecializationDecl *Partial
@@ -2888,6 +2926,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateParams,
ClassTemplate,
Converted,
+ TemplateArgs.data(),
+ TemplateArgs.size(),
PrevPartial);
if (PrevPartial) {
@@ -2898,6 +2938,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
}
Specialization = Partial;
+ // If we are providing an explicit specialization of a member class
+ // template specialization, make a note of that.
+ if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+ PrevPartial->setMemberSpecialization();
+
// 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
@@ -2905,6 +2950,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
llvm::SmallVector<bool, 8> DeducibleParams;
DeducibleParams.resize(TemplateParams->size());
MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+ TemplateParams->getDepth(),
DeducibleParams);
unsigned NumNonDeducible = 0;
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
@@ -3070,8 +3116,6 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
/// for those cases where they are required and determining whether the
/// new specialization/instantiation will have any effect.
///
-/// \param S the semantic analysis object.
-///
/// \param NewLoc the location of the new explicit specialization or
/// instantiation.
///
@@ -3089,14 +3133,13 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
///
/// \returns true if there was an error that should prevent the introduction of
/// the new declaration into the AST, false otherwise.
-static bool
-CheckSpecializationInstantiationRedecl(Sema &S,
- SourceLocation NewLoc,
- TemplateSpecializationKind NewTSK,
- NamedDecl *PrevDecl,
- TemplateSpecializationKind PrevTSK,
- SourceLocation PrevPointOfInstantiation,
- bool &SuppressNew) {
+bool
+Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew) {
SuppressNew = false;
switch (NewTSK) {
@@ -3134,9 +3177,9 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// before the first use of that specialization that would cause an
// implicit instantiation to take place, in every translation unit in
// which such a use occurs; no diagnostic is required.
- S.Diag(NewLoc, diag::err_specialization_after_instantiation)
+ Diag(NewLoc, diag::err_specialization_after_instantiation)
<< PrevDecl;
- S.Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+ Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
<< (PrevTSK != TSK_ImplicitInstantiation);
return true;
@@ -3169,10 +3212,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// If an entity is the subject of both an explicit instantiation
// declaration and an explicit instantiation definition in the same
// translation unit, the definition shall follow the declaration.
- S.Diag(NewLoc,
- diag::err_explicit_instantiation_declaration_after_definition);
- S.Diag(PrevPointOfInstantiation,
- diag::note_explicit_instantiation_definition_here);
+ Diag(NewLoc,
+ diag::err_explicit_instantiation_declaration_after_definition);
+ Diag(PrevPointOfInstantiation,
+ diag::note_explicit_instantiation_definition_here);
assert(PrevPointOfInstantiation.isValid() &&
"Explicit instantiation without point of instantiation?");
SuppressNew = true;
@@ -3198,10 +3241,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// In C++98/03 mode, we only give an extension warning here, because it
// is not not harmful to try to explicitly instantiate something that
// has been explicitly specialized.
- if (!S.getLangOptions().CPlusPlus0x) {
- S.Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
+ if (!getLangOptions().CPlusPlus0x) {
+ Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
<< PrevDecl;
- S.Diag(PrevDecl->getLocation(),
+ Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
}
SuppressNew = true;
@@ -3217,10 +3260,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// For a given template and a given set of template-arguments,
// - an explicit instantiation definition shall appear at most once
// in a program,
- S.Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+ Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
<< PrevDecl;
- S.Diag(PrevPointOfInstantiation,
- diag::note_previous_explicit_instantiation);
+ Diag(PrevPointOfInstantiation,
+ diag::note_previous_explicit_instantiation);
SuppressNew = true;
return false;
}
@@ -3264,7 +3307,7 @@ bool
Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
NamedDecl *&PrevDecl) {
@@ -3333,7 +3376,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
- // explicitly specialized then that spe- cialization shall be declared
+ // explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
@@ -3620,7 +3663,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
: TSK_ExplicitInstantiationDeclaration;
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
// Check that the template argument list is well-formed for this
@@ -3659,7 +3702,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (PrevDecl) {
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK,
+ if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
PrevDecl,
PrevDecl->getSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
@@ -3723,8 +3766,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Specialization);
- Specialization->setPointOfInstantiation(TemplateNameLoc);
-
// C++ [temp.explicit]p3:
// A definition of a class template or class member template
// shall be in scope at the point of the explicit instantiation of
@@ -3736,8 +3777,12 @@ Sema::ActOnExplicitInstantiation(Scope *S,
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition(Context));
if (!Def)
- InstantiateClassTemplateSpecialization(Specialization, TSK);
- else // Instantiate the members of this class template specialization.
+ InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
+
+ // Instantiate the members of this class template specialization.
+ Def = cast_or_null<ClassTemplateSpecializationDecl>(
+ Specialization->getDefinition(Context));
+ if (Def)
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
return DeclPtrTy::make(Specialization);
@@ -3819,7 +3864,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
bool SuppressNew = false;
assert(MSInfo && "No member specialization information?");
- if (CheckSpecializationInstantiationRedecl(*this, TemplateLoc, TSK,
+ if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
PrevDecl,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
@@ -3843,13 +3888,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Diag(Pattern->getLocation(), diag::note_forward_declaration)
<< Pattern;
return true;
- } else if (InstantiateClass(NameLoc, Record, Def,
- getTemplateInstantiationArgs(Record),
- TSK))
- return true;
- } else // Instantiate all of the members of the class.
- InstantiateClassMembers(NameLoc, RecordDef,
- getTemplateInstantiationArgs(Record), TSK);
+ } else {
+ if (InstantiateClass(NameLoc, Record, Def,
+ getTemplateInstantiationArgs(Record),
+ TSK))
+ return true;
+
+ RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ if (!RecordDef)
+ return true;
+ }
+ }
+
+ // Instantiate all of the members of the class.
+ InstantiateClassMembers(NameLoc, RecordDef,
+ getTemplateInstantiationArgs(Record), TSK);
// FIXME: We don't have any representation for explicit instantiations of
// member classes. Such a representation is not needed for compilation, but it
@@ -3968,8 +4021,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
assert(MSInfo && "Missing static data member specialization info?");
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
- Prev,
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew))
@@ -3990,9 +4042,9 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- if (D.getKind() == Declarator::DK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getTemplateId();
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
@@ -4068,7 +4120,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (PrevDecl) {
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
PrevDecl,
PrevDecl->getTemplateSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
@@ -4095,7 +4147,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
//
// C++98 has the same restriction, just worded differently.
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
- if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
@@ -4277,6 +4329,13 @@ namespace {
/// \brief Returns the name of the entity whose type is being rebuilt.
DeclarationName getBaseEntity() { return Entity; }
+ /// \brief Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) {
+ this->Loc = Loc;
+ this->Entity = Entity;
+ }
+
/// \brief Transforms an expression by returning the expression itself
/// (an identity function).
///
@@ -4290,25 +4349,13 @@ namespace {
/// refers to a member of the current instantiation, and then
/// type-checking and building a QualifiedNameType (when possible).
QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
- QualType TransformTypenameType(TypenameType *T);
};
}
QualType
CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
TypenameTypeLoc TL) {
- QualType Result = TransformTypenameType(TL.getTypePtr());
- if (Result.isNull())
- return QualType();
-
- TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
-
- return Result;
-}
-
-QualType
-CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
+ TypenameType *T = TL.getTypePtr();
NestedNameSpecifier *NNS
= TransformNestedNameSpecifier(T->getQualifier(),
@@ -4322,12 +4369,14 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
CXXScopeSpec SS;
SS.setRange(SourceRange(getBaseLocation()));
SS.setScopeRep(NNS);
+
+ QualType Result;
if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0)
- return QualType(T, 0);
+ Result = QualType(T, 0);
// Rebuild the typename type, which will probably turn into a
// QualifiedNameType.
- if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
+ else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
QualType NewTemplateId
= TransformType(QualType(TemplateId, 0));
if (NewTemplateId.isNull())
@@ -4335,12 +4384,16 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
if (NNS == T->getQualifier() &&
NewTemplateId == QualType(TemplateId, 0))
- return QualType(T, 0);
-
- return getDerived().RebuildTypenameType(NNS, NewTemplateId);
- }
+ Result = QualType(T, 0);
+ else
+ Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+ } else
+ Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(),
+ SourceRange(TL.getNameLoc()));
- return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+ TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
}
/// \brief Rebuilds a type within the context of the current instantiation.
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 2a44f83598e8..7b5ad7fc640e 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -90,7 +90,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
Value.extOrTrunc(AllowedBits);
Value.setIsSigned(T->isSignedIntegerType());
- Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T);
+ Deduced[NTTP->getIndex()] = TemplateArgument(Value, T);
return Sema::TDK_Success;
}
@@ -102,7 +102,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
if (PrevValuePtr->isNegative()) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
+ Info.SecondArg = TemplateArgument(Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
@@ -115,7 +115,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
if (Value != PrevValue) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
+ Info.SecondArg = TemplateArgument(Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
@@ -433,7 +433,7 @@ DeduceTemplateArguments(ASTContext &Context,
if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = Deduced[Index];
- Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+ Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_InconsistentQuals;
}
@@ -445,7 +445,7 @@ DeduceTemplateArguments(ASTContext &Context,
DeducedType = Context.getCanonicalType(DeducedType);
if (Deduced[Index].isNull())
- Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType);
+ Deduced[Index] = TemplateArgument(DeducedType);
else {
// C++ [temp.deduct.type]p2:
// [...] If type deduction cannot be done for any P/A pair, or if for
@@ -457,7 +457,7 @@ DeduceTemplateArguments(ASTContext &Context,
Info.Param
= cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = Deduced[Index];
- Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+ Info.SecondArg = TemplateArgument(Arg);
return Sema::TDK_Inconsistent;
}
}
@@ -465,8 +465,8 @@ DeduceTemplateArguments(ASTContext &Context,
}
// Set up the template argument deduction information for a failure.
- Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
- Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
+ Info.FirstArg = TemplateArgument(ParamIn);
+ Info.SecondArg = TemplateArgument(ArgIn);
// Check the cv-qualifiers on the parameter and argument types.
if (!(TDF & TDF_IgnoreQualifiers)) {
@@ -695,7 +695,7 @@ DeduceTemplateArguments(ASTContext &Context,
CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
BaseEnd = Next->bases_end();
- Base != BaseEnd; ++Base) {
+ Base != BaseEnd; ++Base) {
assert(Base->getType()->isRecordType() &&
"Base class that isn't a record?");
ToVisit.push_back(Base->getType()->getAs<RecordType>());
@@ -982,18 +982,41 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// 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) {
+ const TemplateArgumentLoc *PartialTemplateArgs
+ = Partial->getTemplateArgsAsWritten();
+ unsigned N = Partial->getNumTemplateArgsAsWritten();
+ llvm::SmallVector<TemplateArgumentLoc, 16> InstArgs(N);
+ for (unsigned I = 0; I != N; ++I) {
Decl *Param = const_cast<NamedDecl *>(
ClassTemplate->getTemplateParameters()->getParam(I));
- TemplateArgument InstArg
- = Subst(PartialTemplateArgs[I],
- MultiLevelTemplateArgumentList(*DeducedArgumentList));
- if (InstArg.isNull()) {
+ if (Subst(PartialTemplateArgs[I], InstArgs[I],
+ MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[I];
+ Info.FirstArg = PartialTemplateArgs[I].getArgument();
return TDK_SubstitutionFailure;
}
+ }
+
+ TemplateArgumentListBuilder ConvertedInstArgs(
+ ClassTemplate->getTemplateParameters(), N);
+
+ if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+ /*LAngle*/ SourceLocation(),
+ InstArgs.data(), N,
+ /*RAngle*/ SourceLocation(),
+ false, ConvertedInstArgs)) {
+ // FIXME: fail with more useful information?
+ return TDK_SubstitutionFailure;
+ }
+
+ for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
+ // We don't really care if we overwrite the internal structures of
+ // the arg list builder, because we're going to throw it all away.
+ TemplateArgument &InstArg
+ = const_cast<TemplateArgument&>(ConvertedInstArgs.getFlatArguments()[I]);
+
+ Decl *Param = const_cast<NamedDecl *>(
+ ClassTemplate->getTemplateParameters()->getParam(I));
if (InstArg.getKind() == TemplateArgument::Expression) {
// When the argument is an expression, check the expression result
@@ -1004,7 +1027,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[I];
+ Info.FirstArg = Partial->getTemplateArgs()[I];
return TDK_SubstitutionFailure;
}
} else if (TemplateTemplateParmDecl *TTP
@@ -1013,7 +1036,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
if (!DRE || CheckTemplateArgument(TTP, DRE)) {
Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[I];
+ Info.FirstArg = Partial->getTemplateArgs()[I];
return TDK_SubstitutionFailure;
}
}
@@ -1072,7 +1095,7 @@ static bool isSimpleTemplateIdType(QualType T) {
Sema::TemplateDeductionResult
Sema::SubstituteExplicitTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
llvm::SmallVectorImpl<TemplateArgument> &Deduced,
llvm::SmallVectorImpl<QualType> &ParamTypes,
@@ -1290,7 +1313,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
@@ -1460,7 +1483,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
@@ -1643,15 +1666,15 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
// performed on the types used for partial ordering:
// - If P is a reference type, P is replaced by the type referred to.
CanQual<ReferenceType> ParamRef = Param->getAs<ReferenceType>();
- if (ParamRef)
+ if (!ParamRef.isNull())
Param = ParamRef->getPointeeType();
// - If A is a reference type, A is replaced by the type referred to.
CanQual<ReferenceType> ArgRef = Arg->getAs<ReferenceType>();
- if (ArgRef)
+ if (!ArgRef.isNull())
Arg = ArgRef->getPointeeType();
- if (QualifierComparisons && ParamRef && ArgRef) {
+ if (QualifierComparisons && !ParamRef.isNull() && !ArgRef.isNull()) {
// C++0x [temp.deduct.partial]p6:
// If both P and A were reference types (before being replaced with the
// type referred to above), determine which of the two types (if any) is
@@ -1690,6 +1713,7 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
static void
MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
bool OnlyDeduced,
+ unsigned Level,
llvm::SmallVectorImpl<bool> &Deduced);
/// \brief Determine whether the function template \p FT1 is at least as
@@ -1782,18 +1806,22 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
case TPOC_Call: {
unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
for (unsigned I = 0; I != NumParams; ++I)
- ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
+ ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
+ TemplateParams->getDepth(),
UsedParameters);
break;
}
case TPOC_Conversion:
- ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+ ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+ TemplateParams->getDepth(),
UsedParameters);
break;
case TPOC_Other:
- ::MarkUsedTemplateParameters(S, FD2->getType(), false, UsedParameters);
+ ::MarkUsedTemplateParameters(S, FD2->getType(), false,
+ TemplateParams->getDepth(),
+ UsedParameters);
break;
}
@@ -2065,6 +2093,7 @@ static void
MarkUsedTemplateParameters(Sema &SemaRef,
const TemplateArgument &TemplateArg,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used);
/// \brief Mark the template parameters that are used by the given
@@ -2073,6 +2102,7 @@ static void
MarkUsedTemplateParameters(Sema &SemaRef,
const Expr *E,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
// FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
// find other occurrences of template parameters.
@@ -2085,7 +2115,8 @@ MarkUsedTemplateParameters(Sema &SemaRef,
if (!NTTP)
return;
- Used[NTTP->getIndex()] = true;
+ if (NTTP->getDepth() == Depth)
+ Used[NTTP->getIndex()] = true;
}
/// \brief Mark the template parameters that are used by the given
@@ -2094,13 +2125,15 @@ static void
MarkUsedTemplateParameters(Sema &SemaRef,
NestedNameSpecifier *NNS,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
if (!NNS)
return;
- MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Used);
+ MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth,
+ Used);
MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
}
/// \brief Mark the template parameters that are used by the given
@@ -2109,16 +2142,20 @@ static void
MarkUsedTemplateParameters(Sema &SemaRef,
TemplateName Name,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(Template))
- Used[TTP->getIndex()] = true;
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ }
return;
}
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
- MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Used);
+ MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
+ Depth, Used);
}
/// \brief Mark the template parameters that are used by the given
@@ -2126,6 +2163,7 @@ MarkUsedTemplateParameters(Sema &SemaRef,
static void
MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
if (T.isNull())
return;
@@ -2140,6 +2178,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
MarkUsedTemplateParameters(SemaRef,
cast<PointerType>(T)->getPointeeType(),
OnlyDeduced,
+ Depth,
Used);
break;
@@ -2147,6 +2186,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
MarkUsedTemplateParameters(SemaRef,
cast<BlockPointerType>(T)->getPointeeType(),
OnlyDeduced,
+ Depth,
Used);
break;
@@ -2155,69 +2195,74 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
MarkUsedTemplateParameters(SemaRef,
cast<ReferenceType>(T)->getPointeeType(),
OnlyDeduced,
+ Depth,
Used);
break;
case Type::MemberPointer: {
const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced,
- Used);
+ Depth, Used);
MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
break;
}
case Type::DependentSizedArray:
MarkUsedTemplateParameters(SemaRef,
cast<DependentSizedArrayType>(T)->getSizeExpr(),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
// Fall through to check the element type
case Type::ConstantArray:
case Type::IncompleteArray:
MarkUsedTemplateParameters(SemaRef,
cast<ArrayType>(T)->getElementType(),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
break;
case Type::Vector:
case Type::ExtVector:
MarkUsedTemplateParameters(SemaRef,
cast<VectorType>(T)->getElementType(),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
break;
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);
MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
- Used);
+ Depth, Used);
MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
- Used);
+ Depth, Used);
break;
}
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced,
- Used);
+ Depth, Used);
for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced,
- Used);
+ Depth, Used);
break;
}
- case Type::TemplateTypeParm:
- Used[cast<TemplateTypeParmType>(T)->getIndex()] = true;
+ case Type::TemplateTypeParm: {
+ const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T);
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
break;
+ }
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
= cast<TemplateSpecializationType>(T);
MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
- Used);
+ Depth, Used);
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
- MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Used);
+ MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+ Used);
break;
}
@@ -2225,14 +2270,14 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
if (!OnlyDeduced)
MarkUsedTemplateParameters(SemaRef,
cast<ComplexType>(T)->getElementType(),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
break;
case Type::Typename:
if (!OnlyDeduced)
MarkUsedTemplateParameters(SemaRef,
cast<TypenameType>(T)->getQualifier(),
- OnlyDeduced, Used);
+ OnlyDeduced, Depth, Used);
break;
// None of these types have any template parameters in them.
@@ -2259,6 +2304,7 @@ static void
MarkUsedTemplateParameters(Sema &SemaRef,
const TemplateArgument &TemplateArg,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
switch (TemplateArg.getKind()) {
case TemplateArgument::Null:
@@ -2267,25 +2313,27 @@ MarkUsedTemplateParameters(Sema &SemaRef,
case TemplateArgument::Type:
MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced,
- Used);
+ Depth, Used);
break;
case TemplateArgument::Declaration:
if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl()))
- Used[TTP->getIndex()] = true;
+ = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) {
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ }
break;
case TemplateArgument::Expression:
MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
- Used);
+ Depth, Used);
break;
case TemplateArgument::Pack:
for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
PEnd = TemplateArg.pack_end();
P != PEnd; ++P)
- MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Used);
+ MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used);
break;
}
}
@@ -2301,10 +2349,11 @@ MarkUsedTemplateParameters(Sema &SemaRef,
/// deduced.
void
Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
- bool OnlyDeduced,
+ bool OnlyDeduced, unsigned Depth,
llvm::SmallVectorImpl<bool> &Used) {
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, Used);
+ ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced,
+ Depth, Used);
}
/// \brief Marks all of the template parameters that will be deduced by a
@@ -2319,5 +2368,5 @@ void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(),
- true, Deduced);
+ true, TemplateParams->getDepth(), Deduced);
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 53d158088c8e..dfe37d8caf17 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -392,6 +392,13 @@ namespace {
/// \brief Returns the name of the entity being instantiated, if any.
DeclarationName getBaseEntity() { return Entity; }
+ /// \brief Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) {
+ this->Loc = Loc;
+ this->Entity = Entity;
+ }
+
/// \brief Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(Decl *D);
@@ -415,8 +422,10 @@ namespace {
/// elaborated type.
QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag);
- Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
- Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
+ Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E,
+ bool isAddressOfOperand);
+ Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
+ bool isAddressOfOperand);
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
@@ -528,7 +537,8 @@ TemplateInstantiator::RebuildElaboratedType(QualType T,
}
Sema::OwningExprResult
-TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
+TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E,
+ bool isAddressOfOperand) {
if (!E->isTypeDependent())
return SemaRef.Owned(E->Retain());
@@ -551,62 +561,64 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
}
Sema::OwningExprResult
-TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Clean this up a bit
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) {
- assert(false && "Cannot reduce non-type template parameter depth yet");
- return getSema().ExprError();
- }
-
- // If the corresponding template argument is NULL or non-existent, it's
- // because we are performing instantiation from explicitly-specified
- // template arguments in a function template, but there were some
- // arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
- NTTP->getPosition()))
- return SemaRef.Owned(E->Retain());
-
- const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
- NTTP->getPosition());
-
- // The template argument itself might be an expression, in which
- // case we just return that expression.
- if (Arg.getKind() == TemplateArgument::Expression)
- return SemaRef.Owned(Arg.getAsExpr()->Retain());
-
- if (Arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
-
- VD = cast_or_null<ValueDecl>(
+ if (NTTP->getDepth() < TemplateArgs.getNumLevels()) {
+
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+ NTTP->getPosition()))
+ return SemaRef.Owned(E->Retain());
+
+ const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
+ NTTP->getPosition());
+
+ // The template argument itself might be an expression, in which
+ // case we just return that expression.
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr()->Retain());
+
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ VD = cast_or_null<ValueDecl>(
getSema().FindInstantiatedDecl(VD, TemplateArgs));
- if (!VD)
- return SemaRef.ExprError();
+ if (!VD)
+ return SemaRef.ExprError();
- return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
- /*FIXME:*/false, /*FIXME:*/false);
- }
+ return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+ /*FIXME:*/false, /*FIXME:*/false);
+ }
- assert(Arg.getKind() == TemplateArgument::Integral);
- QualType T = Arg.getIntegralType();
- if (T->isCharType() || T->isWideCharType())
- return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
- Arg.getAsIntegral()->getZExtValue(),
- T->isWideCharType(),
- T,
- E->getSourceRange().getBegin()));
- if (T->isBooleanType())
- return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral()->getBoolValue(),
- T,
- E->getSourceRange().getBegin()));
-
- assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
- return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
- *Arg.getAsIntegral(),
+ assert(Arg.getKind() == TemplateArgument::Integral);
+ QualType T = Arg.getIntegralType();
+ if (T->isCharType() || T->isWideCharType())
+ return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+ Arg.getAsIntegral()->getZExtValue(),
+ T->isWideCharType(),
T,
E->getSourceRange().getBegin()));
+ if (T->isBooleanType())
+ return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+ Arg.getAsIntegral()->getBoolValue(),
+ T,
+ E->getSourceRange().getBegin()));
+
+ assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
+ return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+ *Arg.getAsIntegral(),
+ T,
+ E->getSourceRange().getBegin()));
+ }
+
+ // We have a non-type template parameter that isn't fully substituted;
+ // FindInstantiatedDecl will find it in the local instantiation scope.
}
NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs);
@@ -618,11 +630,22 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
// FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
InstD = InstD->getUnderlyingDecl();
- // FIXME: nested-name-specifier for QualifiedDeclRefExpr
+ CXXScopeSpec SS;
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+
+ SS.setScopeRep(Qualifier);
+ SS.setRange(E->getQualifierRange());
+ }
+
return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD,
/*FIXME:*/false,
- /*FIXME:*/0,
- /*FIXME:*/false);
+ &SS,
+ isAddressOfOperand);
}
QualType
@@ -838,6 +861,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+ Spec->setTemplateSpecializationKind(TSK);
+ Spec->setPointOfInstantiation(PointOfInstantiation);
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
@@ -892,18 +919,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (!Invalid)
Consumer.HandleTagDeclDefinition(Instantiation);
- // If this is an explicit instantiation, instantiate our members, too.
- if (!Invalid && TSK != TSK_ImplicitInstantiation) {
- Inst.Clear();
- InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs,
- TSK);
- }
-
return Invalid;
}
bool
Sema::InstantiateClassTemplateSpecialization(
+ SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain) {
@@ -921,10 +942,6 @@ Sema::InstantiateClassTemplateSpecialization(
// declaration (C++0x [temp.explicit]p10); go ahead and perform the
// explicit instantiation.
ClassTemplateSpec->setSpecializationKind(TSK);
- InstantiateClassTemplateSpecializationMembers(
- /*FIXME?*/ClassTemplateSpec->getPointOfInstantiation(),
- ClassTemplateSpec,
- TSK);
return false;
}
@@ -969,62 +986,72 @@ Sema::InstantiateClassTemplateSpecialization(
}
}
- if (Matched.size() == 1) {
- // -- If exactly one matching specialization is found, the
- // instantiation is generated from that specialization.
- Pattern = Matched[0].first;
- ClassTemplateSpec->setInstantiationOf(Matched[0].first, 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.
+ if (Matched.size() >= 1) {
llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
- for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (getMoreSpecializedPartialSpecialization(P->first, Best->first)
- == P->first)
- Best = P;
- }
-
- // Determine if the best partial specialization is more specialized than
- // the others.
- bool Ambiguous = false;
- for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
- PEnd = Matched.end();
- P != PEnd; ++P) {
- if (P != Best &&
- getMoreSpecializedPartialSpecialization(P->first, Best->first)
- != Best->first) {
- Ambiguous = true;
- break;
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- 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.
+ for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (getMoreSpecializedPartialSpecialization(P->first, Best->first)
+ == P->first)
+ Best = P;
}
- }
-
- if (Ambiguous) {
- // Partial ordering did not produce a clear winner. Complain.
- ClassTemplateSpec->setInvalidDecl();
- Diag(ClassTemplateSpec->getPointOfInstantiation(),
- diag::err_partial_spec_ordering_ambiguous)
- << ClassTemplateSpec;
- // Print the matching partial specializations.
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ bool Ambiguous = false;
for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
PEnd = Matched.end();
- P != PEnd; ++P)
- Diag(P->first->getLocation(), diag::note_partial_spec_match)
- << getTemplateArgumentBindingsText(P->first->getTemplateParameters(),
- *P->second);
-
- return true;
+ P != PEnd; ++P) {
+ if (P != Best &&
+ getMoreSpecializedPartialSpecialization(P->first, Best->first)
+ != Best->first) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ if (Ambiguous) {
+ // Partial ordering did not produce a clear winner. Complain.
+ ClassTemplateSpec->setInvalidDecl();
+ Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+ << ClassTemplateSpec;
+
+ // Print the matching partial specializations.
+ for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P)
+ Diag(P->first->getLocation(), diag::note_partial_spec_match)
+ << getTemplateArgumentBindingsText(P->first->getTemplateParameters(),
+ *P->second);
+
+ return true;
+ }
}
// Instantiate using the best class template partial specialization.
- Pattern = Best->first;
+ ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first;
+ while (OrigPartialSpec->getInstantiatedFromMember()) {
+ // If we've found an explicit specialization of this class template,
+ // stop here and use that as the pattern.
+ if (OrigPartialSpec->isMemberSpecialization())
+ break;
+
+ OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+ }
+
+ Pattern = OrigPartialSpec;
ClassTemplateSpec->setInstantiationOf(Best->first, Best->second);
} else {
// -- If no matches are found, the instantiation is generated
@@ -1042,12 +1069,9 @@ Sema::InstantiateClassTemplateSpecialization(
Pattern = OrigTemplate->getTemplatedDecl();
}
- // Note that this is an instantiation.
- ClassTemplateSpec->setSpecializationKind(TSK);
-
- bool Result = InstantiateClass(ClassTemplateSpec->getPointOfInstantiation(),
- ClassTemplateSpec, Pattern,
- getTemplateInstantiationArgs(ClassTemplateSpec),
+ bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec,
+ Pattern,
+ getTemplateInstantiationArgs(ClassTemplateSpec),
TSK,
Complain);
@@ -1071,48 +1095,112 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
DEnd = Instantiation->decls_end();
D != DEnd; ++D) {
+ bool SuppressNew = false;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
- if (Function->getInstantiatedFromMemberFunction()) {
- // If this member was explicitly specialized, do nothing.
- if (Function->getTemplateSpecializationKind() ==
- TSK_ExplicitSpecialization)
+ if (FunctionDecl *Pattern
+ = Function->getInstantiatedFromMemberFunction()) {
+ MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Function,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
+ continue;
+
+ if (Function->getBody())
continue;
+
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Pattern->getBody())
+ continue;
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+
+ InstantiateFunctionDefinition(PointOfInstantiation, Function);
+ } else {
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
}
-
- if (!Function->getBody() && TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateFunctionDefinition(PointOfInstantiation, Function);
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
if (Var->isStaticDataMember()) {
- // If this member was explicitly specialized, do nothing.
- if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Var,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
continue;
- Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
-
- if (TSK == TSK_ExplicitInstantiationDefinition)
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Var->getInstantiatedFromStaticDataMember()
+ ->getOutOfLineDefinition())
+ continue;
+
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
- }
+ } else {
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
+ }
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
if (Record->isInjectedClassName())
continue;
- assert(Record->getInstantiatedFromMemberClass() &&
- "Missing instantiated-from-template information");
-
- // If this member was explicitly specialized, do nothing.
- if (Record->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Record,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
continue;
- if (!Record->getDefinition(Context))
- InstantiateClass(PointOfInstantiation, Record,
- Record->getInstantiatedFromMemberClass(),
+ CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+ assert(Pattern && "Missing instantiated-from-template information");
+
+ if (!Record->getDefinition(Context)) {
+ if (!Pattern->getDefinition(Context)) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ continue;
+ }
+
+ InstantiateClass(PointOfInstantiation, Record, Pattern,
TemplateArgs,
TSK);
+ }
- InstantiateClassMembers(PointOfInstantiation, Record, TemplateArgs,
- TSK);
+ Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ if (Pattern)
+ InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
+ TSK);
}
}
}
@@ -1178,9 +1266,10 @@ Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
return Instantiator.TransformTemplateName(Name);
}
-TemplateArgument Sema::Subst(TemplateArgument Arg,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
+bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
DeclarationName());
- return Instantiator.TransformTemplateArgument(Arg);
+
+ return Instantiator.TransformTemplateArgument(Input, Output);
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index be4adbc93d15..7288ae29a0e3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -56,12 +56,12 @@ namespace {
Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
- Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
Decl *VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
// Base case. FIXME: Remove once we can instantiate everything.
@@ -82,6 +82,10 @@ namespace {
TemplateParameterList *
SubstTemplateParams(TemplateParameterList *List);
+
+ bool InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
};
}
@@ -99,20 +103,20 @@ TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
bool Invalid = false;
- QualType T = D->getUnderlyingType();
- if (T->isDependentType()) {
- T = SemaRef.SubstType(T, TemplateArgs,
- D->getLocation(), D->getDeclName());
- if (T.isNull()) {
+ DeclaratorInfo *DI = D->getTypeDeclaratorInfo();
+ if (DI->getType()->isDependentType()) {
+ DI = SemaRef.SubstType(DI, TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI) {
Invalid = true;
- T = SemaRef.Context.IntTy;
+ DI = SemaRef.Context.getTrivialDeclaratorInfo(SemaRef.Context.IntTy);
}
}
// Create the new typedef
TypedefDecl *Typedef
= TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getIdentifier(), T);
+ D->getIdentifier(), DI);
if (Invalid)
Typedef->setInvalidDecl();
@@ -161,7 +165,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// which they were instantiated.
if (Var->isStaticDataMember())
SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
- TSK_ImplicitInstantiation);
+ TSK_ImplicitInstantiation);
if (D->getInit()) {
OwningExprResult Init
@@ -389,7 +393,25 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
return 0;
}
+namespace {
+ class SortDeclByLocation {
+ SourceManager &SourceMgr;
+
+ public:
+ explicit SortDeclByLocation(SourceManager &SourceMgr)
+ : SourceMgr(SourceMgr) { }
+
+ bool operator()(const Decl *X, const Decl *Y) const {
+ return SourceMgr.isBeforeInTranslationUnit(X->getLocation(),
+ Y->getLocation());
+ }
+ };
+}
+
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // Create a local instantiation scope for this class template, which
+ // will contain the instantiations of the template parameters.
+ Sema::LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
@@ -406,32 +428,83 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
= ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getIdentifier(), InstParams, RecordInst, 0);
RecordInst->setDescribedClassTemplate(Inst);
- Inst->setAccess(D->getAccess());
+ if (D->getFriendObjectKind())
+ Inst->setObjectOfFriendDecl(true);
+ else
+ Inst->setAccess(D->getAccess());
Inst->setInstantiatedFromMemberTemplate(D);
// Trigger creation of the type for the instantiation.
SemaRef.Context.getTypeDeclType(RecordInst);
+ // Finish handling of friends.
+ if (Inst->getFriendObjectKind()) {
+ return Inst;
+ }
+
Owner->addDecl(Inst);
+
+ // First, we sort the partial specializations by location, so
+ // that we instantiate them in the order they were declared.
+ llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = D->getPartialSpecializations().begin(),
+ PEnd = D->getPartialSpecializations().end();
+ P != PEnd; ++P)
+ PartialSpecs.push_back(&*P);
+ std::sort(PartialSpecs.begin(), PartialSpecs.end(),
+ SortDeclByLocation(SemaRef.SourceMgr));
+
+ // Instantiate all of the partial specializations of this member class
+ // template.
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+ InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]);
+
return Inst;
}
Decl *
TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
- assert(false &&"Partial specializations of member templates are unsupported");
+ ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+
+ // Lookup the already-instantiated declaration in the instantiation
+ // of the class template and return that.
+ DeclContext::lookup_result Found
+ = Owner->lookup(ClassTemplate->getDeclName());
+ if (Found.first == Found.second)
+ return 0;
+
+ ClassTemplateDecl *InstClassTemplate
+ = dyn_cast<ClassTemplateDecl>(*Found.first);
+ if (!InstClassTemplate)
+ return 0;
+
+ Decl *DCanon = D->getCanonicalDecl();
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = InstClassTemplate->getPartialSpecializations().begin(),
+ PEnd = InstClassTemplate->getPartialSpecializations().end();
+ P != PEnd; ++P) {
+ if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+ return &*P;
+ }
+
return 0;
}
Decl *
TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
- // FIXME: Dig out the out-of-line definition of this function template?
-
+ // Create a local instantiation scope for this function template, which
+ // will contain the instantiations of the template parameters and then get
+ // merged with the local instantiation scope for the function template
+ // itself.
+ Sema::LocalInstantiationScope Scope(SemaRef);
+
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
return NULL;
-
+
FunctionDecl *Instantiated = 0;
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
@@ -516,7 +589,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef);
+ Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
@@ -530,7 +603,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
D->getDeclName(), T, D->getDeclaratorInfo(),
D->getStorageClass(),
- D->isInline(), D->hasWrittenPrototype());
+ D->isInlineSpecified(), D->hasWrittenPrototype());
Function->setLexicalDeclContext(Owner);
// Attach the parameters
@@ -645,7 +718,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef);
+ Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
@@ -666,14 +739,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Name, T,
Constructor->getDeclaratorInfo(),
Constructor->isExplicit(),
- Constructor->isInline(), false);
+ Constructor->isInlineSpecified(), false);
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
Name = SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
Destructor->getLocation(), Name,
- T, Destructor->isInline(), false);
+ T, Destructor->isInlineSpecified(), false);
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
CanQualType ConvTy
= SemaRef.Context.getCanonicalType(
@@ -683,12 +756,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
Conversion->getLocation(), Name,
T, Conversion->getDeclaratorInfo(),
- Conversion->isInline(),
+ Conversion->isInlineSpecified(),
Conversion->isExplicit());
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
D->getDeclName(), T, D->getDeclaratorInfo(),
- D->isStatic(), D->isInline());
+ D->isStatic(), D->isInlineSpecified());
}
if (TemplateParams) {
@@ -776,24 +849,27 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
}
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
- QualType OrigT = SemaRef.SubstType(D->getOriginalType(), TemplateArgs,
- D->getLocation(), D->getDeclName());
- if (OrigT.isNull())
+ QualType T;
+ DeclaratorInfo *DI = D->getDeclaratorInfo();
+ if (DI) {
+ DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ if (DI) T = DI->getType();
+ } else {
+ T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ DI = 0;
+ }
+
+ if (T.isNull())
return 0;
- QualType T = SemaRef.adjustParameterType(OrigT);
+ T = SemaRef.adjustParameterType(T);
// Allocate the parameter
- ParmVarDecl *Param = 0;
- if (T == OrigT)
- Param = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getIdentifier(), T, D->getDeclaratorInfo(),
- D->getStorageClass(), 0);
- else
- Param = OriginalParmVarDecl::Create(SemaRef.Context, Owner,
- D->getLocation(), D->getIdentifier(),
- T, D->getDeclaratorInfo(), OrigT,
- D->getStorageClass(), 0);
+ ParmVarDecl *Param
+ = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getIdentifier(), T, DI, D->getStorageClass(), 0);
// Mark the default argument as being uninstantiated.
if (D->hasUninstantiatedDefaultArg())
@@ -808,15 +884,6 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
return Param;
}
-Decl *
-TemplateDeclInstantiator::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
- // Since parameter types can decay either before or after
- // instantiation, we simply treat OriginalParmVarDecls as
- // ParmVarDecls the same way, and create one or the other depending
- // on what happens after template instantiation.
- return VisitParmVarDecl(D);
-}
-
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *D) {
// TODO: don't always clone when decls are refcounted.
@@ -826,26 +893,71 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *Inst =
TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- TTPT->getDepth(), TTPT->getIndex(),
+ TTPT->getDepth() - 1, TTPT->getIndex(),
TTPT->getName(),
D->wasDeclaredWithTypename(),
D->isParameterPack());
+ // FIXME: Do we actually want to perform substitution here? I don't think
+ // we do.
if (D->hasDefaultArgument()) {
- QualType DefaultPattern = D->getDefaultArgument();
- QualType DefaultInst
+ DeclaratorInfo *DefaultPattern = D->getDefaultArgumentInfo();
+ DeclaratorInfo *DefaultInst
= SemaRef.SubstType(DefaultPattern, TemplateArgs,
D->getDefaultArgumentLoc(),
D->getDeclName());
Inst->setDefaultArgument(DefaultInst,
- D->getDefaultArgumentLoc(),
D->defaultArgumentWasInherited() /* preserve? */);
}
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
+ NonTypeTemplateParmDecl *D) {
+ // Substitute into the type of the non-type template parameter.
+ QualType T;
+ DeclaratorInfo *DI = D->getDeclaratorInfo();
+ if (DI) {
+ DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ if (DI) T = DI->getType();
+ } else {
+ T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+ D->getDeclName());
+ DI = 0;
+ }
+ if (T.isNull())
+ return 0;
+
+ // Check that this type is acceptable for a non-type template parameter.
+ bool Invalid = false;
+ T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation());
+ if (T.isNull()) {
+ T = SemaRef.Context.IntTy;
+ Invalid = true;
+ }
+
+ NonTypeTemplateParmDecl *Param
+ = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getDepth() - 1, D->getPosition(),
+ D->getIdentifier(), T, DI);
+ if (Invalid)
+ Param->setInvalidDecl();
+
+ Param->setDefaultArgument(D->getDefaultArgument());
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+ return Param;
+}
+
Decl *
TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
NestedNameSpecifier *NNS =
@@ -913,6 +1025,136 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
return InstL;
}
+/// \brief Instantiate the declaration of a class template partial
+/// specialization.
+///
+/// \param ClassTemplate the (instantiated) class template that is partially
+// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) class template partial
+/// specialization that we are instantiating.
+///
+/// \returns true if there was an error, false otherwise.
+bool
+TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ // Create a local instantiation scope for this class template partial
+ // specialization, which will contain the instantiations of the template
+ // parameters.
+ Sema::LocalInstantiationScope Scope(SemaRef);
+
+ // Substitute into the template parameters of the class template partial
+ // specialization.
+ TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return true;
+
+ // Substitute into the template arguments of the class template partial
+ // specialization.
+ const TemplateArgumentLoc *PartialSpecTemplateArgs
+ = PartialSpec->getTemplateArgsAsWritten();
+ unsigned N = PartialSpec->getNumTemplateArgsAsWritten();
+
+ llvm::SmallVector<TemplateArgumentLoc, 4> InstTemplateArgs(N);
+ for (unsigned I = 0; I != N; ++I) {
+ if (SemaRef.Subst(PartialSpecTemplateArgs[I], InstTemplateArgs[I],
+ TemplateArgs))
+ return true;
+ }
+
+
+ // Check that the template argument list is well-formed for this
+ // class template.
+ TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
+ InstTemplateArgs.size());
+ if (SemaRef.CheckTemplateArgumentList(ClassTemplate,
+ PartialSpec->getLocation(),
+ /*FIXME:*/PartialSpec->getLocation(),
+ InstTemplateArgs.data(),
+ InstTemplateArgs.size(),
+ /*FIXME:*/PartialSpec->getLocation(),
+ false,
+ Converted))
+ return true;
+
+ // Figure out where to insert this class template partial specialization
+ // in the member template's set of class template partial specializations.
+ llvm::FoldingSetNodeID ID;
+ ClassTemplatePartialSpecializationDecl::Profile(ID,
+ Converted.getFlatArguments(),
+ Converted.flatSize(),
+ SemaRef.Context);
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *PrevDecl
+ = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
+ InsertPos);
+
+ // Build the canonical type that describes the converted template
+ // arguments of the class template partial specialization.
+ QualType CanonType
+ = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+ Converted.getFlatArguments(),
+ Converted.flatSize());
+
+ // Build the fully-sugared type for this class template
+ // specialization as the user wrote in the specialization
+ // itself. This means that we'll pretty-print the type retrieved
+ // from the specialization's declaration the way that the user
+ // actually wrote the specialization, rather than formatting the
+ // name based on the "canonical" representation used to store the
+ // template arguments in the specialization.
+ QualType WrittenTy
+ = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+ InstTemplateArgs.data(),
+ InstTemplateArgs.size(),
+ CanonType);
+
+ if (PrevDecl) {
+ // We've already seen a partial specialization with the same template
+ // parameters and template arguments. This can happen, for example, when
+ // substituting the outer template arguments ends up causing two
+ // class template partial specializations of a member class template
+ // to have identical forms, e.g.,
+ //
+ // template<typename T, typename U>
+ // struct Outer {
+ // template<typename X, typename Y> struct Inner;
+ // template<typename Y> struct Inner<T, Y>;
+ // template<typename Y> struct Inner<U, Y>;
+ // };
+ //
+ // Outer<int, int> outer; // error: the partial specializations of Inner
+ // // have the same signature.
+ SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
+ << WrittenTy;
+ SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
+ << SemaRef.Context.getTypeDeclType(PrevDecl);
+ return true;
+ }
+
+
+ // Create the class template partial specialization declaration.
+ ClassTemplatePartialSpecializationDecl *InstPartialSpec
+ = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, Owner,
+ PartialSpec->getLocation(),
+ InstParams,
+ ClassTemplate,
+ Converted,
+ InstTemplateArgs.data(),
+ InstTemplateArgs.size(),
+ 0);
+ InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+ InstPartialSpec->setTypeAsWritten(WrittenTy);
+
+ // Add this partial specialization to the set of class template partial
+ // specializations.
+ ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
+ InsertPos);
+ return false;
+}
+
/// \brief Does substitution on the type of the given function, including
/// all of the function parameters.
///
@@ -1065,20 +1307,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
return;
// Find the function body that we'll be substituting.
- const FunctionDecl *PatternDecl = 0;
- if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) {
- while (Primary->getInstantiatedFromMemberTemplate()) {
- // If we have hit a point where the user provided a specialization of
- // this template, we're done looking.
- if (Primary->isMemberSpecialization())
- break;
-
- Primary = Primary->getInstantiatedFromMemberTemplate();
- }
-
- PatternDecl = Primary->getTemplatedDecl();
- } else
- PatternDecl = Function->getInstantiatedFromMemberFunction();
+ const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
Stmt *Pattern = 0;
if (PatternDecl)
Pattern = PatternDecl->getBody(PatternDecl);
@@ -1108,7 +1337,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// to which they refer.
if (Function->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration &&
- PatternDecl->isOutOfLine() && !PatternDecl->isInline())
+ !PatternDecl->isInlined())
return;
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
@@ -1199,24 +1428,17 @@ void Sema::InstantiateStaticDataMemberDefinition(
// Find the out-of-line definition of this static data member.
VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
- bool FoundOutOfLineDef = false;
assert(Def && "This data member was not instantiated from a template?");
- assert(Def->isStaticDataMember() && "Not a static data member?");
- for (VarDecl::redecl_iterator RD = Def->redecls_begin(),
- RDEnd = Def->redecls_end();
- RD != RDEnd; ++RD) {
- if (RD->getLexicalDeclContext()->isFileContext()) {
- Def = *RD;
- FoundOutOfLineDef = true;
- }
- }
+ assert(Def->isStaticDataMember() && "Not a static data member?");
+ Def = Def->getOutOfLineDefinition();
- if (!FoundOutOfLineDef) {
+ if (!Def) {
// We did not find an out-of-line definition of this static data member,
// so we won't perform any instantiation. Rather, we rely on the user to
// instantiate this definition (or provide a specialization for it) in
// another translation unit.
if (DefinitionRequired) {
+ Def = Var->getInstantiatedFromStaticDataMember();
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_member)
<< 2 << Var->getDeclName() << Var->getDeclContext();
@@ -1379,6 +1601,22 @@ static bool isInstantiationOf(FunctionTemplateDecl *Pattern,
return false;
}
+static bool
+isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern,
+ ClassTemplatePartialSpecializationDecl *Instance) {
+ Pattern
+ = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl());
+ do {
+ Instance = cast<ClassTemplatePartialSpecializationDecl>(
+ Instance->getCanonicalDecl());
+ if (Pattern == Instance)
+ return true;
+ Instance = Instance->getInstantiatedFromMember();
+ } while (Instance);
+
+ return false;
+}
+
static bool isInstantiationOf(CXXRecordDecl *Pattern,
CXXRecordDecl *Instance) {
Pattern = Pattern->getCanonicalDecl();
@@ -1469,6 +1707,11 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
+ return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
+ PartialSpec);
+
if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
if (!Field->getDeclName()) {
// This is an unnamed field.
@@ -1550,7 +1793,9 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
}
DeclContext *ParentDC = D->getDeclContext();
- if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) {
+ if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
+ isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ ParentDC->isFunctionOrMethod()) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 49f7119c8b06..0003b1b0c419 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -31,36 +31,58 @@ using namespace clang;
/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
QualType Sema::adjustParameterType(QualType T) {
// C99 6.7.5.3p7:
- if (T->isArrayType()) {
- // C99 6.7.5.3p7:
- // A declaration of a parameter as "array of type" shall be
- // adjusted to "qualified pointer to type", where the type
- // qualifiers (if any) are those specified within the [ and ] of
- // the array type derivation.
+ // A declaration of a parameter as "array of type" shall be
+ // adjusted to "qualified pointer to type", where the type
+ // qualifiers (if any) are those specified within the [ and ] of
+ // the array type derivation.
+ if (T->isArrayType())
return Context.getArrayDecayedType(T);
- } else if (T->isFunctionType())
- // C99 6.7.5.3p8:
- // A declaration of a parameter as "function returning type"
- // shall be adjusted to "pointer to function returning type", as
- // in 6.3.2.1.
+
+ // C99 6.7.5.3p8:
+ // A declaration of a parameter as "function returning type"
+ // shall be adjusted to "pointer to function returning type", as
+ // in 6.3.2.1.
+ if (T->isFunctionType())
return Context.getPointerType(T);
return T;
}
+
+
+/// isOmittedBlockReturnType - Return true if this declarator is missing a
+/// return type because this is a omitted return type on a block literal.
+static bool isOmittedBlockReturnType(const Declarator &D) {
+ if (D.getContext() != Declarator::BlockLiteralContext ||
+ D.getDeclSpec().hasTypeSpecifier())
+ return false;
+
+ if (D.getNumTypeObjects() == 0)
+ return true; // ^{ ... }
+
+ if (D.getNumTypeObjects() == 1 &&
+ D.getTypeObject(0).Kind == DeclaratorChunk::Function)
+ return true; // ^(int X, float Y) { ... }
+
+ return false;
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
-/// \param DS the declaration specifiers
-/// \param DeclLoc The location of the declarator identifier or invalid if none.
+/// \param D the declarator containing the declaration specifier.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
-QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
- SourceLocation DeclLoc,
- bool &isInvalid) {
+static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
- QualType Result;
+ const DeclSpec &DS = TheDeclarator.getDeclSpec();
+ SourceLocation DeclLoc = TheDeclarator.getIdentifierLoc();
+ if (DeclLoc.isInvalid())
+ DeclLoc = DS.getSourceRange().getBegin();
+
+ ASTContext &Context = TheSema.Context;
+ QualType Result;
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_void:
Result = Context.VoidTy;
@@ -80,13 +102,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
Result = Context.WCharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
- Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+ TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType());
Result = Context.getSignedWCharType();
} else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
- Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+ TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType());
Result = Context.getUnsignedWCharType();
}
@@ -109,6 +131,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
DS.getNumProtocolQualifiers());
break;
}
+
+ // If this is a missing declspec in a block literal return context, then it
+ // is inferred from the return statements inside the block.
+ if (isOmittedBlockReturnType(TheDeclarator)) {
+ Result = Context.DependentTy;
+ break;
+ }
// Unspecified typespec defaults to int in C90. However, the C90 grammar
// [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
@@ -117,13 +146,11 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// allowed to be completely missing a declspec. This is handled in the
// parser already though by it pretending to have seen an 'int' in this
// case.
- if (getLangOptions().ImplicitInt) {
+ if (TheSema.getLangOptions().ImplicitInt) {
// In C89 mode, we only warn if there is a completely missing declspec
// when one is not allowed.
if (DS.isEmpty()) {
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getSourceRange().getBegin();
- Diag(DeclLoc, diag::ext_missing_declspec)
+ TheSema.Diag(DeclLoc, diag::ext_missing_declspec)
<< DS.getSourceRange()
<< CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(),
"int");
@@ -134,19 +161,17 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// specifiers in each declaration, and in the specifier-qualifier list in
// each struct declaration and type name."
// FIXME: Does Microsoft really have the implicit int extension in C++?
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getSourceRange().getBegin();
-
- if (getLangOptions().CPlusPlus && !getLangOptions().Microsoft) {
- Diag(DeclLoc, diag::err_missing_type_specifier)
+ if (TheSema.getLangOptions().CPlusPlus &&
+ !TheSema.getLangOptions().Microsoft) {
+ TheSema.Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
// When this occurs in C++ code, often something is very broken with the
// value being declared, poison it as invalid so we don't get chains of
// errors.
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
} else {
- Diag(DeclLoc, diag::ext_missing_type_specifier)
+ TheSema.Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
}
}
@@ -158,14 +183,28 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
case DeclSpec::TSW_short: Result = Context.ShortTy; break;
case DeclSpec::TSW_long: Result = Context.LongTy; break;
- case DeclSpec::TSW_longlong: Result = Context.LongLongTy; break;
+ case DeclSpec::TSW_longlong:
+ Result = Context.LongLongTy;
+
+ // long long is a C99 feature.
+ if (!TheSema.getLangOptions().C99 &&
+ !TheSema.getLangOptions().CPlusPlus0x)
+ TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+ break;
}
} else {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
- case DeclSpec::TSW_longlong: Result =Context.UnsignedLongLongTy; break;
+ case DeclSpec::TSW_longlong:
+ Result = Context.UnsignedLongLongTy;
+
+ // long long is a C99 feature.
+ if (!TheSema.getLangOptions().C99 &&
+ !TheSema.getLangOptions().CPlusPlus0x)
+ TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+ break;
}
}
break;
@@ -181,44 +220,47 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
case DeclSpec::TST_decimal32: // _Decimal32
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
- Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
+ TheSema.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
Result = Context.IntTy;
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
break;
case DeclSpec::TST_class:
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct: {
- Decl *D = static_cast<Decl *>(DS.getTypeRep());
+ TypeDecl *D = cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
break;
}
+ // If the type is deprecated or unavailable, diagnose it.
+ TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
+
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 &&
- "Can't handle qualifiers on typedef names yet!");
+ DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
+
// TypeQuals handled by caller.
- Result = Context.getTypeDeclType(cast<TypeDecl>(D));
+ Result = Context.getTypeDeclType(D);
// In C++, make an ElaboratedType.
- if (getLangOptions().CPlusPlus) {
+ if (TheSema.getLangOptions().CPlusPlus) {
TagDecl::TagKind Tag
= TagDecl::getTagKindForTypeSpec(DS.getTypeSpecType());
Result = Context.getElaboratedType(Result, Tag);
}
if (D->isInvalidDecl())
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
break;
}
case DeclSpec::TST_typename: {
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
- Result = GetTypeFromParser(DS.getTypeRep());
+ Result = TheSema.GetTypeFromParser(DS.getTypeRep());
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
if (const ObjCInterfaceType *
@@ -240,31 +282,22 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
else if (Result->isObjCClassType()) {
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getSourceRange().getBegin();
// Class<protocol-list>
Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy,
(ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers());
} else {
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getSourceRange().getBegin();
- Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
+ TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
<< DS.getSourceRange();
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
}
}
- // If this is a reference to an invalid typedef, propagate the invalidity.
- if (TypedefType *TDT = dyn_cast<TypedefType>(Result))
- if (TDT->getDecl()->isInvalidDecl())
- isInvalid = true;
-
// TypeQuals handled by caller.
break;
}
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
- Result = GetTypeFromParser(DS.getTypeRep());
+ Result = TheSema.GetTypeFromParser(DS.getTypeRep());
assert(!Result.isNull() && "Didn't get a type for typeof?");
// TypeQuals handled by caller.
Result = Context.getTypeOfType(Result);
@@ -280,10 +313,10 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Expr *E = static_cast<Expr *>(DS.getTypeRep());
assert(E && "Didn't get an expression for decltype?");
// TypeQuals handled by caller.
- Result = BuildDecltypeType(E);
+ Result = TheSema.BuildDecltypeType(E);
if (Result.isNull()) {
Result = Context.IntTy;
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
}
break;
}
@@ -295,14 +328,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
case DeclSpec::TST_error:
Result = Context.IntTy;
- isInvalid = true;
+ TheDeclarator.setInvalidType(true);
break;
}
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
- if (getLangOptions().Freestanding)
- Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
+ if (TheSema.getLangOptions().Freestanding)
+ TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
Result = Context.getComplexType(Result);
}
@@ -312,7 +345,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// See if there are any attributes on the declspec that apply to the type (as
// opposed to the decl).
if (const AttributeList *AL = DS.getAttributes())
- ProcessTypeAttributeList(Result, AL);
+ TheSema.ProcessTypeAttributeList(Result, AL);
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -329,13 +362,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// If we have a pointer or reference, the pointee must have an object
// incomplete type.
if (!EltTy->isIncompleteOrObjectType()) {
- Diag(DS.getRestrictSpecLoc(),
+ TheSema.Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_invalid_pointee)
<< EltTy << DS.getSourceRange();
TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
}
} else {
- Diag(DS.getRestrictSpecLoc(),
+ TheSema.Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_not_pointer)
<< Result << DS.getSourceRange();
TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
@@ -357,7 +390,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
"Has CVR quals but not C, V, or R?");
Loc = DS.getRestrictSpecLoc();
}
- Diag(Loc, diag::warn_typecheck_function_qualifiers)
+ TheSema.Diag(Loc, diag::warn_typecheck_function_qualifiers)
<< Result << DS.getSourceRange();
}
@@ -407,7 +440,7 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
if (T->isReferenceType()) {
// C++ 8.3.2p4: There shall be no ... pointers to references ...
Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
- << getPrintableNameForEntity(Entity);
+ << getPrintableNameForEntity(Entity) << T;
return QualType();
}
@@ -535,14 +568,14 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
- << getPrintableNameForEntity(Entity);
+ << getPrintableNameForEntity(Entity) << T;
return QualType();
}
// C++ 8.3.2p4: There shall be no ... arrays of references ...
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_array_of_references)
- << getPrintableNameForEntity(Entity);
+ << getPrintableNameForEntity(Entity) << T;
return QualType();
}
@@ -746,7 +779,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
- << (Entity? Entity.getAsString() : "type name");
+ << (Entity? Entity.getAsString() : "type name") << T;
return QualType();
}
@@ -805,6 +838,11 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
QualType QT = QualType::getFromOpaquePtr(Ty);
+ if (QT.isNull()) {
+ if (DInfo) *DInfo = 0;
+ return QualType();
+ }
+
DeclaratorInfo *DI = 0;
if (LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
QT = LIT->getType();
@@ -816,58 +854,31 @@ QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
}
/// GetTypeForDeclarator - Convert the type for the specified
-/// declarator to Type instances. Skip the outermost Skip type
-/// objects.
+/// declarator to Type instances.
///
/// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq
/// owns the declaration of a type (e.g., the definition of a struct
/// type), then *OwnedDecl will receive the owned declaration.
QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
- DeclaratorInfo **DInfo, unsigned Skip,
+ DeclaratorInfo **DInfo,
TagDecl **OwnedDecl) {
- bool OmittedReturnType = false;
-
- if (D.getContext() == Declarator::BlockLiteralContext
- && Skip == 0
- && !D.getDeclSpec().hasTypeSpecifier()
- && (D.getNumTypeObjects() == 0
- || (D.getNumTypeObjects() == 1
- && D.getTypeObject(0).Kind == DeclaratorChunk::Function)))
- OmittedReturnType = true;
-
- // long long is a C99 feature.
- if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
- D.getDeclSpec().getTypeSpecWidth() == DeclSpec::TSW_longlong)
- Diag(D.getDeclSpec().getTypeSpecWidthLoc(), diag::ext_longlong);
-
// Determine the type of the declarator. Not all forms of declarator
// have a type.
QualType T;
- switch (D.getKind()) {
- case Declarator::DK_Abstract:
- case Declarator::DK_Normal:
- case Declarator::DK_Operator:
- case Declarator::DK_TemplateId: {
- const DeclSpec &DS = D.getDeclSpec();
- if (OmittedReturnType) {
- // We default to a dependent type initially. Can be modified by
- // the first return statement.
- T = Context.DependentTy;
- } else {
- bool isInvalid = false;
- T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
- if (isInvalid)
- D.setInvalidType(true);
- else if (OwnedDecl && DS.isTypeSpecOwned())
- *OwnedDecl = cast<TagDecl>((Decl *)DS.getTypeRep());
- }
+ switch (D.getName().getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_TemplateId:
+ T = ConvertDeclSpecToType(D, *this);
+
+ if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned())
+ *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
break;
- }
- case Declarator::DK_Constructor:
- case Declarator::DK_Destructor:
- case Declarator::DK_Conversion:
+ case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedId::IK_DestructorName:
+ case UnqualifiedId::IK_ConversionFunctionId:
// Constructors and destructors don't have return types. Use
// "void" instead. Conversion operators will check their return
// types separately.
@@ -926,8 +937,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
- for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &DeclType = D.getTypeObject(e-i-1+Skip);
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
switch (DeclType.Kind) {
default: assert(0 && "Unknown decltype!");
case DeclaratorChunk::BlockPointer:
@@ -1190,7 +1201,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (getLangOptions().CPlusPlus && T->isFunctionType()) {
const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
- assert(FnTy && "Why oh why is there not a FunctionProtoType here ?");
+ assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
// C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type
// for a nonstatic member function, the function type to which a pointer
@@ -1224,7 +1235,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.isInvalidType())
*DInfo = 0;
else
- *DInfo = GetDeclaratorInfoForDeclarator(D, T, Skip);
+ *DInfo = GetDeclaratorInfoForDeclarator(D, T);
}
return T;
@@ -1289,6 +1300,21 @@ namespace {
Visit(TL.getBaseTypeLoc());
}
}
+ void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+ DeclaratorInfo *DInfo = 0;
+ Sema::GetTypeFromParser(DS.getTypeRep(), &DInfo);
+
+ // If we got no declarator info from previous Sema routines,
+ // just fill with the typespec loc.
+ if (!DInfo) {
+ TL.initialize(DS.getTypeSpecTypeLoc());
+ return;
+ }
+
+ TemplateSpecializationTypeLoc OldTL =
+ cast<TemplateSpecializationTypeLoc>(DInfo->getTypeLoc());
+ TL.copy(OldTL);
+ }
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
TL.initialize(DS.getTypeSpecTypeLoc());
@@ -1366,11 +1392,11 @@ namespace {
///
/// \param T QualType referring to the type as written in source code.
DeclaratorInfo *
-Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
+Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T) {
DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T);
UnqualTypeLoc CurrTL = DInfo->getTypeLoc().getUnqualifiedLoc();
- for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -1463,7 +1489,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
DeclaratorInfo *DInfo = 0;
TagDecl *OwnedTag = 0;
- QualType T = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, &OwnedTag);
+ QualType T = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag);
if (D.isInvalidType())
return true;
@@ -1655,13 +1681,10 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (const RecordType *Record = T->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
- if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
- if (Loc.isValid())
- ClassTemplateSpec->setPointOfInstantiation(Loc);
- return InstantiateClassTemplateSpecialization(ClassTemplateSpec,
+ if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
+ return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
- }
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
@@ -1669,13 +1692,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
assert(MSInfo && "Missing member specialization information?");
// This record was instantiated from a class within a template.
if (MSInfo->getTemplateSpecializationKind()
- != TSK_ExplicitSpecialization) {
- MSInfo->setPointOfInstantiation(Loc);
+ != TSK_ExplicitSpecialization)
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
- }
}
}
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 7e0972fe03c4..5713da9fa590 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -290,23 +290,43 @@ public:
/// declaration stored within the template argument and constructs a
/// new template argument from the transformed result. Subclasses may
/// override this function to provide alternate behavior.
- TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
+ ///
+ /// Returns true if there was an error.
+ bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output);
+
+ /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+ void InventTemplateArgumentLoc(const TemplateArgument &Arg,
+ TemplateArgumentLoc &ArgLoc);
+
+ /// \brief Fakes up a DeclaratorInfo for a type.
+ DeclaratorInfo *InventDeclaratorInfo(QualType T) {
+ return SemaRef.Context.getTrivialDeclaratorInfo(T,
+ getDerived().getBaseLocation());
+ }
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+
QualType
TransformTemplateSpecializationType(const TemplateSpecializationType *T,
QualType ObjectType);
+
+ QualType
+ TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL,
+ QualType ObjectType);
OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
#define STMT(Node, Parent) \
OwningStmtResult Transform##Node(Node *S);
#define EXPR(Node, Parent) \
- OwningExprResult Transform##Node(Node *E);
+ OwningExprResult Transform##Node(Node *E, bool isAddressOfOperand);
#define ABSTRACT_EXPR(Node, Parent)
#include "clang/AST/StmtNodes.def"
@@ -314,35 +334,37 @@ public:
///
/// By default, performs semantic analysis when building the pointer type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildPointerType(QualType PointeeType);
+ QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
/// \brief Build a new block pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the block pointer
/// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildBlockPointerType(QualType PointeeType);
+ QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
- /// \brief Build a new lvalue reference type given the type it references.
+ /// \brief Build a new reference type given the type it references.
///
- /// By default, performs semantic analysis when building the lvalue reference
- /// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildLValueReferenceType(QualType ReferentType);
-
- /// \brief Build a new rvalue reference type given the type it references.
+ /// By default, performs semantic analysis when building the
+ /// reference type. Subclasses may override this routine to provide
+ /// different behavior.
///
- /// By default, performs semantic analysis when building the rvalue reference
- /// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildRValueReferenceType(QualType ReferentType);
+ /// \param LValue whether the type was written with an lvalue sigil
+ /// or an rvalue sigil.
+ QualType RebuildReferenceType(QualType ReferentType,
+ bool LValue,
+ SourceLocation Sigil);
/// \brief Build a new member pointer type given the pointee type and the
/// class type it refers into.
///
/// By default, performs semantic analysis when building the member pointer
/// type. Subclasses may override this routine to provide different behavior.
- QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
+ QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+ SourceLocation Sigil);
/// \brief Build a new Objective C object pointer type.
- QualType RebuildObjCObjectPointerType(QualType PointeeType);
+ QualType RebuildObjCObjectPointerType(QualType PointeeType,
+ SourceLocation Sigil);
/// \brief Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
@@ -366,7 +388,8 @@ public:
QualType RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
- unsigned IndexTypeQuals);
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
/// \brief Build a new incomplete array type given the element type, size
/// modifier, and index type qualifiers.
@@ -375,7 +398,8 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- unsigned IndexTypeQuals);
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
/// \brief Build a new variable-length array type given the element type,
/// size modifier, size expression, and index type qualifiers.
@@ -478,8 +502,11 @@ public:
/// specialization type. Subclasses may override this routine to provide
/// different behavior.
QualType RebuildTemplateSpecializationType(TemplateName Template,
- const TemplateArgument *Args,
- unsigned NumArgs);
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ SourceLocation RAngleLoc);
/// \brief Build a new qualified name type.
///
@@ -509,9 +536,9 @@ public:
/// (or qualified name type). Subclasses may override this routine to provide
/// different behavior.
QualType RebuildTypenameType(NestedNameSpecifier *NNS,
- const IdentifierInfo *Id) {
- return SemaRef.CheckTypenameType(NNS, *Id,
- SourceRange(getDerived().getBaseLocation()));
+ const IdentifierInfo *Id,
+ SourceRange SR) {
+ return SemaRef.CheckTypenameType(NNS, *Id, SR);
}
/// \brief Build a new nested-name-specifier given the prefix and an
@@ -578,7 +605,17 @@ public:
const IdentifierInfo &II,
QualType ObjectType);
-
+ /// \brief Build a new template name given a nested name specifier and the
+ /// overloaded operator name that is referred to as a template.
+ ///
+ /// By default, performs semantic analysis to determine whether the name can
+ /// be resolved to a specific template, then builds the appropriate kind of
+ /// template name. Subclasses may override this routine to provide different
+ /// behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ QualType ObjectType);
+
/// \brief Build a new compound statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -781,11 +818,17 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDeclRefExpr(NamedDecl *ND, SourceLocation Loc) {
+ OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *ND, SourceLocation Loc,
+ bool isAddressOfOperand) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(QualifierRange);
return getSema().BuildDeclarationNameExpr(Loc, ND,
/*FIXME:*/false,
- /*SS=*/0,
- /*FIXME:*/false);
+ &SS,
+ isAddressOfOperand);
}
/// \brief Build a new expression in parentheses.
@@ -841,9 +884,10 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildSizeOfAlignOf(QualType T, SourceLocation OpLoc,
+ OwningExprResult RebuildSizeOfAlignOf(DeclaratorInfo *DInfo,
+ SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
- return getSema().CreateSizeOfAlignOfExpr(T, OpLoc, isSizeOf, R);
+ return getSema().CreateSizeOfAlignOfExpr(DInfo, OpLoc, isSizeOf, R);
}
/// \brief Build a new sizeof or alignof expression with an expression
@@ -1002,9 +1046,9 @@ public:
SourceLocation OpLoc,
SourceLocation AccessorLoc,
IdentifierInfo &Accessor) {
- return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
+ return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
tok::period, AccessorLoc,
- Accessor,
+ DeclarationName(&Accessor),
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
}
@@ -1392,26 +1436,6 @@ public:
T.getAsOpaquePtr(), RParenLoc);
}
- /// \brief Build a new qualified declaration reference expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildQualifiedDeclRefExpr(NestedNameSpecifier *NNS,
- SourceRange QualifierRange,
- NamedDecl *ND,
- SourceLocation Location,
- bool IsAddressOfOperand) {
- CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(NNS);
- return getSema().ActOnDeclarationNameExpr(/*Scope=*/0,
- Location,
- ND->getDeclName(),
- /*Trailing lparen=*/false,
- &SS,
- IsAddressOfOperand);
- }
-
/// \brief Build a new (previously unresolved) declaration reference
/// expression.
///
@@ -1442,7 +1466,7 @@ public:
TemplateName Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- TemplateArgument *TemplateArgs,
+ TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
@@ -1545,7 +1569,7 @@ public:
SourceLocation TemplateNameLoc,
NamedDecl *FirstQualifierInScope,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
OwningExprResult Base = move(BaseE);
@@ -1556,16 +1580,21 @@ public:
SS.setScopeRep(Qualifier);
// FIXME: We're going to end up looking up the template based on its name,
- // twice! Also, duplicates part of Sema::ActOnMemberTemplateIdReferenceExpr.
+ // twice! Also, duplicates part of Sema::BuildMemberAccessExpr.
DeclarationName Name;
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
Name = ActualTemplate->getDeclName();
else if (OverloadedFunctionDecl *Ovl
= Template.getAsOverloadedFunctionDecl())
Name = Ovl->getDeclName();
- else
- Name = Template.getAsDependentTemplateName()->getName();
-
+ else {
+ DependentTemplateName *DTN = Template.getAsDependentTemplateName();
+ if (DTN->isIdentifier())
+ Name = DTN->getIdentifier();
+ else
+ Name = SemaRef.Context.DeclarationNames.getCXXOperatorName(
+ DTN->getOperator());
+ }
return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
OperatorLoc, OpKind,
TemplateNameLoc, Name, true,
@@ -1683,7 +1712,8 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E,
case Stmt::NoStmtClass: break;
#define STMT(Node, Parent) case Stmt::Node##Class: break;
#define EXPR(Node, Parent) \
- case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
+ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E), \
+ isAddressOfOperand);
#include "clang/AST/StmtNodes.def"
}
@@ -1746,6 +1776,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
+ TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
if (T.isNull())
return 0;
@@ -1860,7 +1891,12 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
ObjectType.isNull())
return Name;
- return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType);
+ if (DTN->isIdentifier())
+ return getDerived().RebuildTemplateName(NNS, *DTN->getIdentifier(),
+ ObjectType);
+
+ return getDerived().RebuildTemplateName(NNS, DTN->getOperator(),
+ ObjectType);
}
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
@@ -1891,25 +1927,80 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
}
template<typename Derived>
-TemplateArgument
-TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
+void TreeTransform<Derived>::InventTemplateArgumentLoc(
+ const TemplateArgument &Arg,
+ TemplateArgumentLoc &Output) {
+ SourceLocation Loc = getDerived().getBaseLocation();
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ llvm::llvm_unreachable("null template argument in TreeTransform");
+ break;
+
+ case TemplateArgument::Type:
+ Output = TemplateArgumentLoc(Arg,
+ SemaRef.Context.getTrivialDeclaratorInfo(Arg.getAsType(), Loc));
+
+ break;
+
+ case TemplateArgument::Expression:
+ Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
+ break;
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+ break;
+ }
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformTemplateArgument(
+ const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output) {
+ const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Integral:
- return Arg;
+ Output = Input;
+ return false;
case TemplateArgument::Type: {
- QualType T = getDerived().TransformType(Arg.getAsType());
- if (T.isNull())
- return TemplateArgument();
- return TemplateArgument(Arg.getLocation(), T);
+ DeclaratorInfo *DI = Input.getSourceDeclaratorInfo();
+ if (DI == NULL)
+ DI = InventDeclaratorInfo(Input.getArgument().getAsType());
+
+ DI = getDerived().TransformType(DI);
+ if (!DI) return true;
+
+ Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+ return false;
}
case TemplateArgument::Declaration: {
+ // FIXME: we should never have to transform one of these.
+ DeclarationName Name;
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
+ Name = ND->getDeclName();
+ TemporaryBase Rebase(*this, SourceLocation(), Name);
Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
- if (!D)
- return TemplateArgument();
- return TemplateArgument(Arg.getLocation(), D);
+ if (!D) return true;
+
+ Expr *SourceExpr = Input.getSourceDeclExpression();
+ if (SourceExpr) {
+ EnterExpressionEvaluationContext Unevaluated(getSema(),
+ Action::Unevaluated);
+ Sema::OwningExprResult E = getDerived().TransformExpr(SourceExpr);
+ if (E.isInvalid())
+ SourceExpr = NULL;
+ else {
+ SourceExpr = E.takeAs<Expr>();
+ SourceExpr->Retain();
+ }
+ }
+
+ Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr);
+ return false;
}
case TemplateArgument::Expression: {
@@ -1917,10 +2008,17 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
EnterExpressionEvaluationContext Unevaluated(getSema(),
Action::Unevaluated);
- Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr());
- if (E.isInvalid())
- return TemplateArgument();
- return TemplateArgument(E.takeAs<Expr>());
+ Expr *InputExpr = Input.getSourceExpression();
+ if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+
+ Sema::OwningExprResult E
+ = getDerived().TransformExpr(InputExpr);
+ if (E.isInvalid()) return true;
+
+ Expr *ETaken = E.takeAs<Expr>();
+ ETaken->Retain();
+ Output = TemplateArgumentLoc(TemplateArgument(ETaken), ETaken);
+ return false;
}
case TemplateArgument::Pack: {
@@ -1929,21 +2027,28 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
AEnd = Arg.pack_end();
A != AEnd; ++A) {
- TemplateArgument TA = getDerived().TransformTemplateArgument(*A);
- if (TA.isNull())
- return TA;
- TransformedArgs.push_back(TA);
+ // FIXME: preserve source information here when we start
+ // caring about parameter packs.
+
+ TemplateArgumentLoc InputArg;
+ TemplateArgumentLoc OutputArg;
+ getDerived().InventTemplateArgumentLoc(*A, InputArg);
+ if (getDerived().TransformTemplateArgument(InputArg, OutputArg))
+ return true;
+
+ TransformedArgs.push_back(OutputArg.getArgument());
}
TemplateArgument Result;
Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(),
true);
- return Result;
+ Output = TemplateArgumentLoc(Result, Input.getLocInfo());
+ return false;
}
}
// Work around bogus GCC warning
- return TemplateArgument();
+ return true;
}
//===----------------------------------------------------------------------===//
@@ -2048,7 +2153,8 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
QualType Result = TL.getType(); \
if (getDerived().AlwaysRebuild() || \
PointeeType != TL.getPointeeLoc().getType()) { \
- Result = getDerived().Rebuild##TypeClass(PointeeType); \
+ Result = getDerived().Rebuild##TypeClass(PointeeType, \
+ TL.getSigilLoc()); \
if (Result.isNull()) \
return QualType(); \
} \
@@ -2059,35 +2165,6 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
return Result; \
} while(0)
-// Reference collapsing forces us to transform reference types
-// differently from the other pointer-like types.
-#define TransformReferenceType(TypeClass) do { \
- QualType PointeeType \
- = getDerived().TransformType(TLB, TL.getPointeeLoc()); \
- if (PointeeType.isNull()) \
- return QualType(); \
- \
- QualType Result = TL.getType(); \
- if (getDerived().AlwaysRebuild() || \
- PointeeType != TL.getPointeeLoc().getType()) { \
- Result = getDerived().Rebuild##TypeClass(PointeeType); \
- if (Result.isNull()) \
- return QualType(); \
- } \
- \
- /* Workaround: rebuild doesn't always change the type */ \
- /* FIXME: avoid losing this location information. */ \
- if (Result == PointeeType) \
- return Result; \
- ReferenceTypeLoc NewTL; \
- if (isa<LValueReferenceType>(Result)) \
- NewTL = TLB.push<LValueReferenceTypeLoc>(Result); \
- else \
- NewTL = TLB.push<RValueReferenceTypeLoc>(Result); \
- NewTL.setSigilLoc(TL.getSigilLoc()); \
- return Result; \
-} while (0)
-
template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
BuiltinTypeLoc T) {
@@ -2121,18 +2198,54 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
TransformPointerLikeType(BlockPointerType);
}
+/// Transforms a reference type. Note that somewhat paradoxically we
+/// don't care whether the type itself is an l-value type or an r-value
+/// type; we only care if the type was *written* as an l-value type
+/// or an r-value type.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
+ ReferenceTypeLoc TL) {
+ const ReferenceType *T = TL.getTypePtr();
+
+ // Note that this works with the pointee-as-written.
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeTypeAsWritten()) {
+ Result = getDerived().RebuildReferenceType(PointeeType,
+ T->isSpelledAsLValue(),
+ TL.getSigilLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // r-value references can be rebuilt as l-value references.
+ ReferenceTypeLoc NewTL;
+ if (isa<LValueReferenceType>(Result))
+ NewTL = TLB.push<LValueReferenceTypeLoc>(Result);
+ else
+ NewTL = TLB.push<RValueReferenceTypeLoc>(Result);
+ NewTL.setSigilLoc(TL.getSigilLoc());
+
+ return Result;
+}
+
template<typename Derived>
QualType
TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
LValueReferenceTypeLoc TL) {
- TransformReferenceType(LValueReferenceType);
+ return TransformReferenceType(TLB, TL);
}
template<typename Derived>
QualType
TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
RValueReferenceTypeLoc TL) {
- TransformReferenceType(RValueReferenceType);
+ return TransformReferenceType(TLB, TL);
}
template<typename Derived>
@@ -2155,7 +2268,8 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
if (getDerived().AlwaysRebuild() ||
PointeeType != T->getPointeeType() ||
ClassType != QualType(T->getClass(), 0)) {
- Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+ Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType,
+ TL.getStarLoc());
if (Result.isNull())
return QualType();
}
@@ -2181,7 +2295,8 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
Result = getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeCVRQualifiers());
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2214,7 +2329,8 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType(
ElementType != T->getElementType()) {
Result = getDerived().RebuildIncompleteArrayType(ElementType,
T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers());
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2254,7 +2370,7 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
T->getSizeModifier(),
move(SizeResult),
T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2295,7 +2411,7 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
T->getSizeModifier(),
move(SizeResult),
T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
@@ -2331,7 +2447,8 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
- (ElementType != T->getElementType() && Size.get() != T->getSizeExpr())) {
+ ElementType != T->getElementType() ||
+ Size.get() != T->getSizeExpr()) {
Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
move(Size),
T->getAttributeLoc());
@@ -2687,46 +2804,76 @@ inline QualType
TreeTransform<Derived>::TransformTemplateSpecializationType(
TypeLocBuilder &TLB,
TemplateSpecializationTypeLoc TL) {
- // TODO: figure out how make this work with an ObjectType.
- QualType Result
- = TransformTemplateSpecializationType(TL.getTypePtr(), QualType());
- if (Result.isNull())
- return QualType();
+ return TransformTemplateSpecializationType(TLB, TL, QualType());
+}
- TemplateSpecializationTypeLoc NewTL
- = TLB.push<TemplateSpecializationTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+ const TemplateSpecializationType *TST,
+ QualType ObjectType) {
+ // FIXME: this entire method is a temporary workaround; callers
+ // should be rewritten to provide real type locs.
- return Result;
+ // Fake up a TemplateSpecializationTypeLoc.
+ TypeLocBuilder TLB;
+ TemplateSpecializationTypeLoc TL
+ = TLB.push<TemplateSpecializationTypeLoc>(QualType(TST, 0));
+
+ SourceLocation BaseLoc = getDerived().getBaseLocation();
+
+ TL.setTemplateNameLoc(BaseLoc);
+ TL.setLAngleLoc(BaseLoc);
+ TL.setRAngleLoc(BaseLoc);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+ const TemplateArgument &TA = TST->getArg(i);
+ TemplateArgumentLoc TAL;
+ getDerived().InventTemplateArgumentLoc(TA, TAL);
+ TL.setArgLocInfo(i, TAL.getLocInfo());
+ }
+
+ TypeLocBuilder IgnoredTLB;
+ return TransformTemplateSpecializationType(IgnoredTLB, TL, ObjectType);
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
- const TemplateSpecializationType *T,
- QualType ObjectType) {
+ TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL,
+ QualType ObjectType) {
+ const TemplateSpecializationType *T = TL.getTypePtr();
+
TemplateName Template
= getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
if (Template.isNull())
return QualType();
- llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs;
- NewTemplateArgs.reserve(T->getNumArgs());
- for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
- Arg != ArgEnd; ++Arg) {
- TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg);
- if (NewArg.isNull())
+ llvm::SmallVector<TemplateArgumentLoc, 4> NewTemplateArgs(T->getNumArgs());
+ for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i)
+ if (getDerived().TransformTemplateArgument(TL.getArgLoc(i),
+ NewTemplateArgs[i]))
return QualType();
- NewTemplateArgs.push_back(NewArg);
- }
+ // FIXME: maybe don't rebuild if all the template arguments are the same.
- // FIXME: early abort if all of the template arguments and such are the
- // same.
+ QualType Result =
+ getDerived().RebuildTemplateSpecializationType(Template,
+ TL.getTemplateNameLoc(),
+ TL.getLAngleLoc(),
+ NewTemplateArgs.data(),
+ NewTemplateArgs.size(),
+ TL.getRAngleLoc());
- // FIXME: We're missing the locations of the template name, '<', and '>'.
- return getDerived().RebuildTemplateSpecializationType(Template,
- NewTemplateArgs.data(),
- NewTemplateArgs.size());
+ if (!Result.isNull()) {
+ TemplateSpecializationTypeLoc NewTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+ NewTL.setLAngleLoc(TL.getLAngleLoc());
+ NewTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+ NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+ }
+
+ return Result;
}
template<typename Derived>
@@ -2763,9 +2910,12 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
TypenameTypeLoc TL) {
TypenameType *T = TL.getTypePtr();
+
+ /* FIXME: preserve source information better than this */
+ SourceRange SR(TL.getNameLoc());
+
NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
- SourceRange(/*FIXME:*/getDerived().getBaseLocation()));
+ = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR);
if (!NNS)
return QualType();
@@ -2784,7 +2934,7 @@ QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
} else {
- Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+ Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), SR);
}
if (Result.isNull())
return QualType();
@@ -3268,57 +3418,88 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
//===----------------------------------------------------------------------===//
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
+TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
+TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E,
+ bool isAddressOfOperand) {
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+ }
+
NamedDecl *ND
= dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
if (!ND)
return SemaRef.ExprError();
- if (!getDerived().AlwaysRebuild() && ND == E->getDecl())
+ if (!getDerived().AlwaysRebuild() &&
+ Qualifier == E->getQualifier() &&
+ ND == E->getDecl() &&
+ !E->hasExplicitTemplateArgumentList())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildDeclRefExpr(ND, E->getLocation());
+ // FIXME: We're losing the explicit template arguments in this transformation.
+
+ llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
+ for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+ if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+ TransArgs[I]))
+ return SemaRef.ExprError();
+ }
+
+ // FIXME: Pass the qualifier/qualifier range along.
+ return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
+ ND, E->getLocation(),
+ isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
+TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
+TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
+TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
+TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
+TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
+TreeTransform<Derived>::TransformParenExpr(ParenExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -3332,8 +3513,10 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E,
+ bool isAddressOfOperand) {
+ OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr(),
+ E->getOpcode() == UnaryOperator::AddrOf);
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -3347,16 +3530,19 @@ TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
+ bool isAddressOfOperand) {
if (E->isArgumentType()) {
- QualType T = getDerived().TransformType(E->getArgumentType());
- if (T.isNull())
+ DeclaratorInfo *OldT = E->getArgumentTypeInfo();
+
+ DeclaratorInfo *NewT = getDerived().TransformType(OldT);
+ if (!NewT)
return SemaRef.ExprError();
- if (!getDerived().AlwaysRebuild() && T == E->getArgumentType())
+ if (!getDerived().AlwaysRebuild() && OldT == NewT)
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildSizeOfAlignOf(T, E->getOperatorLoc(),
+ return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(),
E->isSizeOf(),
E->getSourceRange());
}
@@ -3383,7 +3569,8 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
+TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
return SemaRef.ExprError();
@@ -3406,7 +3593,8 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
+TreeTransform<Derived>::TransformCallExpr(CallExpr *E,
+ bool isAddressOfOperand) {
// Transform the callee.
OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
if (Callee.isInvalid())
@@ -3445,7 +3633,8 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
+TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
return SemaRef.ExprError();
@@ -3484,14 +3673,16 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCastExpr(CastExpr *E) {
+TreeTransform<Derived>::TransformCastExpr(CastExpr *E,
+ bool isAddressOfOperand) {
assert(false && "Cannot transform abstract class");
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
+TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E,
+ bool isAddressOfOperand) {
OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
return SemaRef.ExprError();
@@ -3512,13 +3703,15 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCompoundAssignOperator(
- CompoundAssignOperator *E) {
- return getDerived().TransformBinaryOperator(E);
+ CompoundAssignOperator *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformBinaryOperator(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
+TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E,
+ bool isAddressOfOperand) {
OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
if (Cond.isInvalid())
return SemaRef.ExprError();
@@ -3546,7 +3739,12 @@ TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
+TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E,
+ bool isAddressOfOperand) {
+ TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+
+ // FIXME: Will we ever have type information here? It seems like we won't,
+ // so do we even need to transform the type?
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
return SemaRef.ExprError();
@@ -3567,14 +3765,16 @@ TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) {
+TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E,
+ bool isAddressOfOperand) {
assert(false && "Cannot transform abstract class");
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
+TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E,
+ bool isAddressOfOperand) {
QualType T;
{
// FIXME: Source location isn't quite accurate.
@@ -3603,7 +3803,8 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
+TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E,
+ bool isAddressOfOperand) {
QualType T;
{
// FIXME: Source location isn't quite accurate.
@@ -3632,7 +3833,8 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
+TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
return SemaRef.ExprError();
@@ -3651,7 +3853,8 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
+TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E,
+ bool isAddressOfOperand) {
bool InitChanged = false;
ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
@@ -3673,7 +3876,8 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
+TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E,
+ bool isAddressOfOperand) {
Designation Desig;
// transform the initializer value
@@ -3742,7 +3946,12 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformImplicitValueInitExpr(
- ImplicitValueInitExpr *E) {
+ ImplicitValueInitExpr *E,
+ bool isAddressOfOperand) {
+ TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+
+ // FIXME: Will we ever have proper type location here? Will we actually
+ // need to transform the type?
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
return SemaRef.ExprError();
@@ -3756,7 +3965,8 @@ TreeTransform<Derived>::TransformImplicitValueInitExpr(
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
+TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Do we want the type as written?
QualType T;
@@ -3783,7 +3993,8 @@ TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
+TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E,
+ bool isAddressOfOperand) {
bool ArgumentChanged = false;
ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) {
@@ -3807,13 +4018,16 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
/// the corresponding label statement by semantic analysis.
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) {
+TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E,
+ bool isAddressOfOperand) {
return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
E->getLabel());
}
template<typename Derived>
-Sema::OwningExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E,
+ bool isAddressOfOperand) {
OwningStmtResult SubStmt
= getDerived().TransformCompoundStmt(E->getSubStmt(), true);
if (SubStmt.isInvalid())
@@ -3830,7 +4044,8 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) {
+TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E,
+ bool isAddressOfOperand) {
QualType T1, T2;
{
// FIXME: Source location isn't quite accurate.
@@ -3856,7 +4071,8 @@ TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
+TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
if (Cond.isInvalid())
return SemaRef.ExprError();
@@ -3882,18 +4098,22 @@ TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
+TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
if (Callee.isInvalid())
return SemaRef.ExprError();
- OwningExprResult First = getDerived().TransformExpr(E->getArg(0));
+ OwningExprResult First
+ = getDerived().TransformExpr(E->getArg(0),
+ E->getNumArgs() == 1 && E->getOperator() == OO_Amp);
if (First.isInvalid())
return SemaRef.ExprError();
@@ -3919,13 +4139,15 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
- return getDerived().TransformCallExpr(E);
+TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformCallExpr(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
+TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E,
+ bool isAddressOfOperand) {
QualType ExplicitTy;
{
// FIXME: Source location isn't quite accurate.
@@ -3966,33 +4188,38 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
- return getDerived().TransformCXXNamedCastExpr(E);
+TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
- return getDerived().TransformCXXNamedCastExpr(E);
+TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
- CXXReinterpretCastExpr *E) {
- return getDerived().TransformCXXNamedCastExpr(E);
+ CXXReinterpretCastExpr *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
- return getDerived().TransformCXXNamedCastExpr(E);
+TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E,
+ bool isAddressOfOperand) {
+ return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
- CXXFunctionalCastExpr *E) {
+ CXXFunctionalCastExpr *E,
+ bool isAddressOfOperand) {
QualType ExplicitTy;
{
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
@@ -4022,7 +4249,8 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
+TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E,
+ bool isAddressOfOperand) {
if (E->isTypeOperand()) {
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
@@ -4062,20 +4290,23 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
- CXXNullPtrLiteralExpr *E) {
+ CXXNullPtrLiteralExpr *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
@@ -4091,7 +4322,8 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
+TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -4105,7 +4337,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
+ bool isAddressOfOperand) {
ParmVarDecl *Param
= cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getParam()));
if (!Param)
@@ -4120,7 +4353,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
@@ -4139,7 +4373,8 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
+TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E,
+ bool isAddressOfOperand) {
VarDecl *Var
= cast_or_null<VarDecl>(getDerived().TransformDefinition(E->getVarDecl()));
if (!Var)
@@ -4156,7 +4391,8 @@ TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
+TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E,
+ bool isAddressOfOperand) {
// Transform the type that we're allocating
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
QualType AllocType = getDerived().TransformType(E->getAllocatedType());
@@ -4214,7 +4450,8 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
+TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Operand = getDerived().TransformExpr(E->getArgument());
if (Operand.isInvalid())
return SemaRef.ExprError();
@@ -4232,7 +4469,8 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
- CXXPseudoDestructorExpr *E) {
+ CXXPseudoDestructorExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
return SemaRef.ExprError();
@@ -4269,14 +4507,16 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr(
- UnresolvedFunctionNameExpr *E) {
+ UnresolvedFunctionNameExpr *E,
+ bool isAddressOfOperand) {
// There is no transformation we can apply to an unresolved function name.
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getQueriedType());
@@ -4300,34 +4540,9 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) {
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (!NNS)
- return SemaRef.ExprError();
-
- NamedDecl *ND
- = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl()));
- if (!ND)
- return SemaRef.ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- NNS == E->getQualifier() &&
- ND == E->getDecl())
- return SemaRef.Owned(E->Retain());
-
- return getDerived().RebuildQualifiedDeclRefExpr(NNS,
- E->getQualifierRange(),
- ND,
- E->getLocation(),
- /*FIXME:*/false);
-}
-
-template<typename Derived>
-Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
- UnresolvedDeclRefExpr *E) {
+ UnresolvedDeclRefExpr *E,
+ bool isAddressOfOperand) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange());
@@ -4348,12 +4563,15 @@ TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
E->getQualifierRange(),
Name,
E->getLocation(),
- /*FIXME:*/false);
+ isAddressOfOperand);
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {
+TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E,
+ bool isAddressOfOperand) {
+ TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName());
+
TemplateName Template
= getDerived().TransformTemplateName(E->getTemplateName());
if (Template.isNull())
@@ -4367,14 +4585,11 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {
return SemaRef.ExprError();
}
- llvm::SmallVector<TemplateArgument, 4> TransArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
- TemplateArgument TransArg
- = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
- if (TransArg.isNull())
+ if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+ TransArgs[I]))
return SemaRef.ExprError();
-
- TransArgs.push_back(TransArg);
}
// FIXME: Would like to avoid rebuilding if nothing changed, but we can't
@@ -4393,7 +4608,8 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
+TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
@@ -4437,7 +4653,8 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
/// must be unique.
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
+ bool isAddressOfOperand) {
OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -4455,7 +4672,8 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXExprWithTemporaries(
- CXXExprWithTemporaries *E) {
+ CXXExprWithTemporaries *E,
+ bool isAddressOfOperand) {
OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -4468,7 +4686,8 @@ TreeTransform<Derived>::TransformCXXExprWithTemporaries(
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
- CXXTemporaryObjectExpr *E) {
+ CXXTemporaryObjectExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
@@ -4518,7 +4737,8 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
- CXXUnresolvedConstructExpr *E) {
+ CXXUnresolvedConstructExpr *E,
+ bool isAddressOfOperand) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getTypeAsWritten());
if (T.isNull())
@@ -4557,7 +4777,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
- CXXUnresolvedMemberExpr *E) {
+ CXXUnresolvedMemberExpr *E,
+ bool isAddressOfOperand) {
// Transform the base of the expression.
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
@@ -4617,9 +4838,14 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
// FIXME: This is an ugly hack, which forces the same template name to
// be looked up multiple times. Yuck!
- // FIXME: This also won't work for, e.g., x->template operator+<int>
- TemplateName OrigTemplateName
- = SemaRef.Context.getDependentTemplateName(0, Name.getAsIdentifierInfo());
+ TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName());
+ TemplateName OrigTemplateName;
+ if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
+ OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II);
+ else
+ OrigTemplateName
+ = SemaRef.Context.getDependentTemplateName(0,
+ Name.getCXXOverloadedOperator());
TemplateName Template
= getDerived().TransformTemplateName(OrigTemplateName,
@@ -4627,14 +4853,11 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
if (Template.isNull())
return SemaRef.ExprError();
- llvm::SmallVector<TemplateArgument, 4> TransArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
- TemplateArgument TransArg
- = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
- if (TransArg.isNull())
+ if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+ TransArgs[I]))
return SemaRef.ExprError();
-
- TransArgs.push_back(TransArg);
}
return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base),
@@ -4653,13 +4876,15 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
+TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
+TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E,
+ bool isAddressOfOperand) {
// FIXME: poor source location
TemporaryBase Rebase(*this, E->getAtLoc(), DeclarationName());
QualType EncodedType = getDerived().TransformType(E->getEncodedType());
@@ -4677,7 +4902,8 @@ TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
+TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4685,13 +4911,15 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
+TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E,
+ bool isAddressOfOperand) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
+TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E,
+ bool isAddressOfOperand) {
ObjCProtocolDecl *Protocol
= cast_or_null<ObjCProtocolDecl>(
getDerived().TransformDecl(E->getProtocol()));
@@ -4712,7 +4940,8 @@ TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4720,7 +4949,8 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4729,7 +4959,8 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
- ObjCImplicitSetterGetterRefExpr *E) {
+ ObjCImplicitSetterGetterRefExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4737,7 +4968,8 @@ TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) {
+TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4745,7 +4977,8 @@ TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
+TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform Objective-C expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4753,7 +4986,8 @@ TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
+TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E,
+ bool isAddressOfOperand) {
bool ArgumentChanged = false;
ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef);
for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) {
@@ -4776,7 +5010,8 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
+TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform block expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4784,7 +5019,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
+TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E,
+ bool isAddressOfOperand) {
// FIXME: Implement this!
assert(false && "Cannot transform block-related expressions yet");
return SemaRef.Owned(E->Retain());
@@ -4795,48 +5031,42 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
//===----------------------------------------------------------------------===//
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star,
getDerived().getBaseEntity());
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
- return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star,
getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
+TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
+ bool WrittenAsLValue,
+ SourceLocation Sigil) {
+ return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(),
+ Sigil, getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
-}
-
-template<typename Derived>
-QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
- QualType ClassType) {
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+ QualType ClassType,
+ SourceLocation Sigil) {
return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
- getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
+ Sigil, getDerived().getBaseEntity());
}
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
- getDerived().getBaseLocation(),
+TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType,
+ SourceLocation Sigil) {
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Sigil,
getDerived().getBaseEntity());
}
@@ -4880,18 +5110,20 @@ QualType
TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
- unsigned IndexTypeQuals) {
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
- IndexTypeQuals, SourceRange());
+ IndexTypeQuals, BracketsRange);
}
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- unsigned IndexTypeQuals) {
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
- IndexTypeQuals, SourceRange());
+ IndexTypeQuals, BracketsRange);
}
template<typename Derived>
@@ -4980,13 +5212,14 @@ QualType TreeTransform<Derived>::RebuildDecltypeType(ExprArg E) {
template<typename Derived>
QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
- TemplateName Template,
- const TemplateArgument *Args,
- unsigned NumArgs) {
- // FIXME: Missing source locations for the template name, <, >.
- return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(),
- SourceLocation(), Args, NumArgs,
- SourceLocation());
+ TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ SourceLocation RAngleLoc) {
+ return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, LAngleLoc,
+ Args, NumArgs, RAngleLoc);
}
template<typename Derived>
@@ -5058,16 +5291,37 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
CXXScopeSpec SS;
SS.setRange(SourceRange(getDerived().getBaseLocation()));
SS.setScopeRep(Qualifier);
+ UnqualifiedId Name;
+ Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
return getSema().ActOnDependentTemplateName(
/*FIXME:*/getDerived().getBaseLocation(),
- II,
- /*FIXME:*/getDerived().getBaseLocation(),
SS,
+ Name,
ObjectType.getAsOpaquePtr())
.template getAsVal<TemplateName>();
}
template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ QualType ObjectType) {
+ CXXScopeSpec SS;
+ SS.setRange(SourceRange(getDerived().getBaseLocation()));
+ SS.setScopeRep(Qualifier);
+ UnqualifiedId Name;
+ SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
+ Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
+ Operator, SymbolLocations);
+ return getSema().ActOnDependentTemplateName(
+ /*FIXME:*/getDerived().getBaseLocation(),
+ SS,
+ Name,
+ ObjectType.getAsOpaquePtr())
+ .template getAsVal<TemplateName>();
+}
+
+template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
SourceLocation OpLoc,
@@ -5076,10 +5330,18 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
ExprArg Second) {
Expr *FirstExpr = (Expr *)First.get();
Expr *SecondExpr = (Expr *)Second.get();
+ DeclRefExpr *DRE
+ = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts());
bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
// Determine whether this should be a builtin operation.
- if (SecondExpr == 0 || isPostIncDec) {
+ if (Op == OO_Subscript) {
+ if (!FirstExpr->getType()->isOverloadableType() &&
+ !SecondExpr->getType()->isOverloadableType())
+ return getSema().CreateBuiltinArraySubscriptExpr(move(First),
+ DRE->getLocStart(),
+ move(Second), OpLoc);
+ } else if (SecondExpr == 0 || isPostIncDec) {
if (!FirstExpr->getType()->isOverloadableType()) {
// The argument is not of overloadable type, so try to create a
// built-in unary operation.
@@ -5109,9 +5371,6 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// used during overload resolution.
Sema::FunctionSet Functions;
- DeclRefExpr *DRE
- = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts());
-
// FIXME: Do we have to check
// IsAcceptableNonMemberOperatorCandidate for each of these?
for (OverloadIterator F(DRE->getDecl()), FEnd; F != FEnd; ++F)
@@ -5122,7 +5381,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
unsigned NumArgs = 1 + (SecondExpr != 0);
DeclarationName OpName
= SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
- SemaRef.ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+ SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs,
+ Functions);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {
@@ -5131,6 +5391,10 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First));
}
+ if (Op == OO_Subscript)
+ return SemaRef.CreateOverloadedArraySubscriptExpr(DRE->getLocStart(), OpLoc,
+ move(First),move(Second));
+
// Create the overloaded operator invocation for binary operators.
BinaryOperator::Opcode Opc =
BinaryOperator::getOverloadedOpcode(Op);
diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m
index 818922eba925..db1a80b8efd9 100644
--- a/test/Analysis/misc-ps-eager-assume.m
+++ b/test/Analysis/misc-ps-eager-assume.m
@@ -77,3 +77,46 @@ void pr3836(int *a, int *b) {
*a = 1; // no-warning
*b = 1; // no-warning
}
+
+
+//===---------------------------------------------------------------------===//
+// <rdar://problem/7342806>
+// This false positive occured because the symbolic constraint on a short was
+// not maintained via sign extension. The analyzer doesn't properly handle
+// the sign extension, but now tracks the constraint. This particular
+// case relies on -analyzer-eagerly-assume because of the expression
+// 'Flag1 != Count > 0'.
+//===---------------------------------------------------------------------===//
+
+void rdar7342806_aux(short x);
+
+void rdar7342806() {
+ extern short Count;
+ extern short Flag1;
+
+ short *Pointer = 0;
+ short Flag2 = !!Pointer; // Flag2 is false (0).
+ short Ok = 1;
+ short Which;
+
+ if( Flag1 != Count > 0 )
+ // Static analyzer skips this so either
+ // Flag1 is true and Count > 0
+ // or
+ // Flag1 is false and Count <= 0
+ Ok = 0;
+
+ if( Flag1 != Flag2 )
+ // Analyzer skips this so Flag1 and Flag2 have the
+ // same value, both are false because Flag2 is false. And
+ // from that we know Count must be <= 0.
+ Ok = 0;
+
+ for( Which = 0;
+ Which < Count && Ok;
+ Which++ )
+ // This statement can only execute if Count > 0 which can only
+ // happen when Flag1 and Flag2 are both true and Flag2 will only
+ // be true when Pointer is not NULL.
+ rdar7342806_aux(*Pointer); // no-warning
+}
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index b6fff102a701..4cde7726b49b 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -372,3 +372,62 @@ void doSomething_7312221_with_struct(struct rdar_7312221_container *Self) {
}
}
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7332673> - Just more tests cases for regions
+//===----------------------------------------------------------------------===//
+
+void rdar_7332673_test1() {
+ char value[1];
+ if ( *(value) != 1 ) {} // expected-warning{{The left operand of '!=' is a garbage value}}
+}
+void rdar_rdar_7332673_test2_aux(char *x);
+void rdar_7332673_test2() {
+ char *value;
+ if ( rdar_7332673_test2_aux(value) != 1 ) {} // expected-warning{{Pass-by-value argument in function call is undefined}}
+}
+
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7347252>: Because of a bug in
+// RegionStoreManager::RemoveDeadBindings(), the symbol for s->session->p
+// would incorrectly be pruned from the state after the call to
+// rdar7347252_malloc1(), and would incorrectly result in a warning about
+// passing a null pointer to rdar7347252_memcpy().
+//===----------------------------------------------------------------------===//
+
+struct rdar7347252_AA { char *p;};
+typedef struct {
+ struct rdar7347252_AA *session;
+ int t;
+ char *q;
+} rdar7347252_SSL1;
+
+int rdar7347252_f(rdar7347252_SSL1 *s);
+char *rdar7347252_malloc1(int);
+char *rdar7347252_memcpy1(char *d, char *s, int n) __attribute__((nonnull (1,2)));
+
+int rdar7347252(rdar7347252_SSL1 *s) {
+ rdar7347252_f(s); // the SymbolicRegion of 's' is set a default binding of conjured symbol
+ if (s->session->p == ((void*)0)) {
+ if ((s->session->p = rdar7347252_malloc1(10)) == ((void*)0)) {
+ return 0;
+ }
+ rdar7347252_memcpy1(s->session->p, "aa", 2); // no-warning
+ }
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// PR 5316 - "crash when accessing field of lazy compound value"
+// Previously this caused a crash at the MemberExpr '.chr' when loading
+// a field value from a LazyCompoundVal
+//===----------------------------------------------------------------------===//
+
+typedef unsigned int pr5316_wint_t;
+typedef pr5316_wint_t pr5316_REFRESH_CHAR;
+typedef struct {
+ pr5316_REFRESH_CHAR chr;
+}
+pr5316_REFRESH_ELEMENT;
+static void pr5316(pr5316_REFRESH_ELEMENT *dst, const pr5316_REFRESH_ELEMENT *src) {
+ while ((*dst++ = *src++).chr != L'\0') ;
+}
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index fcc13a39a461..947b41ae794c 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -121,12 +121,12 @@ void check_zero_sized_VLA(int x) {
if (x)
return;
- int vla[x]; // expected-warning{{Variable-length array 'vla' has zero elements (undefined behavior)}}
+ int vla[x]; // expected-warning{{Declare variable-length array (VLA) of zero size}}
}
void check_uninit_sized_VLA() {
int x;
- int vla[x]; // expected-warning{{Variable-length array 'vla' garbage value for array size}}
+ int vla[x]; // expected-warning{{Declare variable-length array (VLA) of undefined size}}
}
// sizeof(void)
@@ -154,6 +154,12 @@ void handle_sizeof_void(unsigned flag) {
*p = 1; // no-warning
}
+// check deference of undefined values
+void check_deref_undef(void) {
+ int *p;
+ *p = 0xDEADBEEF; // expected-warning{{Dereference of undefined pointer value}}
+}
+
// PR 3422
void pr3422_helper(char *p);
void pr3422() {
diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c
index 568f14329e9b..e676ea3b3889 100644
--- a/test/Analysis/outofbound.c
+++ b/test/Analysis/outofbound.c
@@ -1,5 +1,5 @@
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
-// XFAIL
+// XFAIL: *
char f1() {
char* s = "abcd";
diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m
index 2833b02f0771..e27cfe758aaf 100644
--- a/test/Analysis/retain-release-gc-only.m
+++ b/test/Analysis/retain-release-gc-only.m
@@ -92,6 +92,7 @@ typedef struct _NSZone NSZone;
+ (id)allocWithZone:(NSZone *)zone;
+ (id)alloc;
- (void)dealloc;
+- (void)release;
@end
@interface NSObject (NSCoderMethods)
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder;
@@ -322,6 +323,16 @@ void rdar_7174400(QCView *view, QCRenderer *renderer, CIContext *context,
}
//===----------------------------------------------------------------------===//
+// <rdar://problem/6250216> Warn against using -[NSAutoreleasePool release] in
+// GC mode
+//===----------------------------------------------------------------------===//
+
+void rdar_6250216(void) {
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ [pool release]; // expected-warning{{Use -drain instead of -release when using NSAutoreleasePool and garbage collection}}
+}
+
+//===----------------------------------------------------------------------===//
// Tests of ownership attributes.
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index e620037b2c14..879e8a0413b4 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1098,6 +1098,32 @@ CVReturn rdar_7283567_2(CFAllocatorRef allocator, size_t width, size_t height,
}
//===----------------------------------------------------------------------===//
+// <rdar://problem/7358899> False leak associated with
+// CGBitmapContextCreateWithData
+//===----------------------------------------------------------------------===//
+typedef uint32_t CGBitmapInfo;
+typedef void (*CGBitmapContextReleaseDataCallback)(void *releaseInfo, void *data);
+
+CGContextRef CGBitmapContextCreateWithData(void *data,
+ size_t width, size_t height, size_t bitsPerComponent,
+ size_t bytesPerRow, CGColorSpaceRef space, CGBitmapInfo bitmapInfo,
+ CGBitmapContextReleaseDataCallback releaseCallback, void *releaseInfo);
+
+void rdar_7358899(void *data,
+ size_t width, size_t height, size_t bitsPerComponent,
+ size_t bytesPerRow, CGColorSpaceRef space, CGBitmapInfo bitmapInfo,
+ CGBitmapContextReleaseDataCallback releaseCallback) {
+
+ // For the allocated object, it doesn't really matter what type it is
+ // for the purpose of this test. All we want to show is that
+ // this is freed later by the callback.
+ NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+
+ CGBitmapContextCreateWithData(data, width, height, bitsPerComponent, // expected-warning{{leak}}
+ bytesPerRow, space, bitmapInfo, releaseCallback, number);
+}
+
+//===----------------------------------------------------------------------===//
// <rdar://problem/7265711> allow 'new', 'copy', 'alloc', 'init' prefix to
// start before '_' when determining Cocoa fundamental rule
//
diff --git a/test/Analysis/uninit-vals-ps-region.c b/test/Analysis/uninit-vals-ps-region.c
index 1561f11c9937..e927a92576e2 100644
--- a/test/Analysis/uninit-vals-ps-region.c
+++ b/test/Analysis/uninit-vals-ps-region.c
@@ -24,9 +24,20 @@ void test_uninit_pos() {
struct TestUninit v1 = { 0, 0 };
struct TestUninit v2 = test_uninit_aux();
int z;
- v1.y = z;
- test_unit_aux2(v2.x + v1.y); // expected-warning{{The right operand of '+' is a garbage value}}
+ v1.y = z; // expected-warning{{Assigned value is garbage or undefined}}
+ test_unit_aux2(v2.x + v1.y);
}
+void test_uninit_pos_2() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2;
+ test_unit_aux2(v2.x + v1.y); // expected-warning{{The left operand of '+' is a garbage value}}
+}
+void test_uninit_pos_3() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2;
+ test_unit_aux2(v1.y + v2.x); // expected-warning{{The right operand of '+' is a garbage value}}
+}
+
void test_uninit_neg() {
struct TestUninit v1 = { 0, 0 };
struct TestUninit v2 = test_uninit_aux();
diff --git a/test/Analysis/unused-ivars.m b/test/Analysis/unused-ivars.m
index aacd44e7e677..9e9360da50c6 100644
--- a/test/Analysis/unused-ivars.m
+++ b/test/Analysis/unused-ivars.m
@@ -43,3 +43,25 @@
b();
}
@end
+
+//===----------------------------------------------------------------------===//
+// <rdar://problem/6260004> Detect that ivar is in use, if used in category
+// in the same file as the implementation
+//===----------------------------------------------------------------------===//
+
+@protocol Protocol6260004
+- (id) getId;
+@end
+
+@interface RDar6260004 {
+@private
+ id x; // no-warning
+}
+@end
+@implementation RDar6260004 @end
+@implementation RDar6260004 (Protocol6260004)
+- (id) getId {
+ return x;
+}
+@end
+
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 66f05bff6994..a83a1993c8f0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -24,6 +24,7 @@ set(CLANG_TEST_DIRECTORIES
include(FindPythonInterp)
if(PYTHONINTERP_FOUND)
+ get_target_triple(TARGET_TRIPLE)
get_target_property(LLVM_TOOLS_PATH clang RUNTIME_OUTPUT_DIRECTORY)
get_target_property(LLVM_LIBS_PATH clang LIBRARY_OUTPUT_DIRECTORY)
set(CLANG_TEST_EXTRA_ARGS)
@@ -32,16 +33,17 @@ if(PYTHONINTERP_FOUND)
endif()
foreach(testdir ${CLANG_TEST_DIRECTORIES})
- add_custom_target(clang-test-${testdir}
+ add_custom_target(clang-test-${testdir}
COMMAND sed -e "s#\@LLVM_SOURCE_DIR\@#${LLVM_MAIN_SRC_DIR}#"
-e "s#\@LLVM_BINARY_DIR\@#${LLVM_BINARY_DIR}#"
-e "s#\@LLVM_TOOLS_DIR\@#${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}#"
-e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
-e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
-e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
+ -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- COMMAND ${PYTHON_EXECUTABLE}
+ COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}/${testdir}
@@ -56,9 +58,10 @@ if(PYTHONINTERP_FOUND)
-e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
-e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
-e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
+ -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- COMMAND ${PYTHON_EXECUTABLE}
+ COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}
@@ -72,12 +75,13 @@ if(PYTHONINTERP_FOUND)
-e "s#\@LLVM_LIBS_DIR\@#${LLVM_LIBS_PATH}/${CMAKE_CFG_INTDIR}#"
-e "s#\@CLANG_SOURCE_DIR\@#${CMAKE_CURRENT_SOURCE_DIR}/..#"
-e "s#\@CLANG_BINARY_DIR\@#${CMAKE_CURRENT_BINARY_DIR}/..#"
+ -e "s#\@TARGET_TRIPLE\@#${TARGET_TRIPLE}#"
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in >
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- COMMAND ${PYTHON_EXECUTABLE}
+ COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests
DEPENDS clang clang-cc index-test c-index-test
COMMENT "Running Clang regression tests")
-endif()
+endif()
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
index b9b136c5061b..141a5732c1d3 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// XFAIL: *
namespace N {
struct S {};
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp
index 9572aaa14273..cebc3e99d09f 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// XFAIL: *
class C {
public:
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
index 15c263467367..9c969c5b7552 100644
--- a/test/CXX/class/class.union/p1.cpp
+++ b/test/CXX/class/class.union/p1.cpp
@@ -16,6 +16,9 @@ class VirtualBase : virtual Okay { // expected-note 3 {{because type 'class Virt
class Ctor {
Ctor() { abort(); } // expected-note 3 {{because type 'class Ctor' has a user-declared constructor}}
};
+class Ctor2 {
+ Ctor2(); // expected-note 3 {{because type 'class Ctor2' has a user-declared constructor}}
+};
class CopyCtor {
CopyCtor(CopyCtor &cc) { abort(); } // expected-note 3 {{because type 'class CopyCtor' has a user-declared copy constructor}}
@@ -34,6 +37,7 @@ union U1 {
Virtual v; // expected-error {{union member 'v' has a non-trivial copy constructor}}
VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}}
Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}}
+ Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial constructor}}
CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
@@ -51,6 +55,9 @@ union U2 {
Ctor ctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}}
} m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
struct {
+ Ctor2 ctor2; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}}
+ } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}}
+ struct {
CopyCtor copyctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
} m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
struct {
@@ -71,6 +78,8 @@ union U3 {
} m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
struct s3 : Ctor { // expected-note {{because type 'struct U3::s3' has a base class with a non-trivial constructor}}
} m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ struct s3a : Ctor2 { // expected-note {{because type 'struct U3::s3a' has a base class with a non-trivial constructor}}
+ } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}}
struct s4 : CopyCtor { // expected-note {{because type 'struct U3::s4' has a base class with a non-trivial copy constructor}}
} m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
struct s5 : CopyAssign { // expected-note {{because type 'struct U3::s5' has a base class with a non-trivial copy assignment operator}}
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
index 3b0e345f0172..dabe13a0ff66 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -verify %s
-// XFAIL
+// XFAIL: *
void f0(void) {
inline void f1(); // expected-error {{'inline' is not allowed on block scope function declaration}}
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
index 0142dcbb055c..7dc65c77d4a9 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -verify %s
-// XFAIL
+// XFAIL: *
void f0() {
}
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
index c5f0a51b22e5..7a1ba3e389ba 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -verify %s
-// XFAIL
+// XFAIL: *
class A {
public:
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp
index 62ae7bfded14..d1251490ac1a 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -verify %s
-// XFAIL
+// XFAIL: *
typedef const int T0;
typedef int& T1;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
index f1413f9b41b8..69e843796ff7 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -verify %s
-// XFAIL
+// XFAIL: *
struct S {
typedef struct A {} A; // expected-note {{previous definition is here}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp
new file mode 100644
index 000000000000..98e1d302a717
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp
@@ -0,0 +1,145 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++ [dcl.ref]p5:
+// There shall be no references to references, no arrays of
+// references, and no pointers to references.
+
+// The crazy formatting in here is to enforce the exact report locations.
+
+typedef int &intref;
+typedef intref &intrefref;
+
+template <class T> class RefMem {
+ T
+ &
+ member;
+};
+
+struct RefRef {
+ int
+ &
+ & // expected-error {{declared as a reference to a reference}}
+ refref0;
+
+ intref
+ &
+ refref1; // collapses
+
+ intrefref
+ &
+ refref2; // collapses
+
+ RefMem
+ <
+ int
+ &
+ >
+ refref3; // collapses
+};
+
+
+template <class T> class PtrMem {
+ T
+ * // expected-error {{declared as a pointer to a reference}}
+ member;
+};
+
+struct RefPtr {
+ typedef
+ int
+ &
+ * // expected-error {{declared as a pointer to a reference}}
+ intrefptr;
+
+ typedef
+ intref
+ * // expected-error {{declared as a pointer to a reference}}
+ intrefptr2;
+
+ int
+ &
+ * // expected-error {{declared as a pointer to a reference}}
+ refptr0;
+
+ intref
+ * // expected-error {{declared as a pointer to a reference}}
+ refptr1;
+
+ PtrMem
+ <
+ int
+ &
+ >
+ refptr2; // expected-note {{in instantiation}}
+};
+
+template <class T> class ArrMem {
+ T
+ member
+ [ // expected-error {{declared as array of references}}
+ 10
+ ];
+};
+template <class T, unsigned N> class DepArrMem {
+ T
+ member
+ [ // expected-error {{declared as array of references}}
+ N
+ ];
+};
+
+struct RefArr {
+ typedef
+ int
+ &
+ intrefarr
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+
+ typedef
+ intref
+ intrefarr
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+
+ int
+ &
+ refarr0
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+ intref
+ refarr1
+ [ // expected-error {{declared as array of references}}
+ 2
+ ];
+ ArrMem
+ <
+ int
+ &
+ >
+ refarr2; // expected-note {{in instantiation}}
+ DepArrMem
+ <
+ int
+ &,
+ 10
+ >
+ refarr3; // expected-note {{in instantiation}}
+};
+
+
+// The declaration of a reference shall contain an initializer
+// (8.5.3) except when the declaration contains an explicit extern
+// specifier (7.1.1), is a class member (9.2) declaration within a
+// class definition, or is the declaration of a parameter or a
+// return type (8.3.5); see 3.1. A reference shall be initialized to
+// refer to a valid object or function. [ Note: in particular, a
+// null reference cannot exist in a well-defined program, because
+// the only way to create such a reference would be to bind it to
+// the "object" obtained by dereferencing a null pointer, which
+// causes undefined behavior. As described in 9.6, a reference
+// cannot be bound directly to a bit-field.
+
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
index afe6ab2b968e..79d6c54e29f0 100644
--- a/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
+++ b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
@@ -1,5 +1,6 @@
// RUN: clang-cc -fsyntax-only -verify %s
+// Test class template partial specializations of member templates.
template<typename T>
struct X0 {
template<typename U> struct Inner0 {
@@ -16,5 +17,39 @@ struct X0<T>::Inner0<const U*> {
static const unsigned value = 2;
};
-// FIXME: Test instantiation of these partial specializations (once they are
-// implemented).
+int array0[X0<int>::Inner0<int>::value == 0? 1 : -1];
+int array1[X0<int>::Inner0<int*>::value == 1? 1 : -1];
+int array2[X0<int>::Inner0<const int*>::value == 2? 1 : -1];
+
+// Make sure we can provide out-of-line class template partial specializations
+// for member templates (and instantiate them).
+template<class T> struct A {
+ struct C {
+ template<class T2> struct B;
+ };
+};
+
+// partial specialization of A<T>::C::B<T2>
+template<class T> template<class T2> struct A<T>::C::B<T2*> { };
+
+A<short>::C::B<int*> absip;
+
+// Check for conflicts during template instantiation.
+template<typename T, typename U>
+struct Outer {
+ template<typename X, typename Y> struct Inner;
+ template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous}}
+ template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}}
+};
+
+Outer<int, int> outer; // expected-note{{instantiation}}
+
+// Test specialization of class template partial specialization members.
+template<> template<typename Z>
+struct X0<float>::Inner0<Z*> {
+ static const unsigned value = 3;
+};
+
+int array3[X0<float>::Inner0<int>::value == 0? 1 : -1];
+int array4[X0<float>::Inner0<int*>::value == 3? 1 : -1];
+int array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1];
diff --git a/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/test/CXX/temp/temp.decls/temp.friend/p5.cpp
index f1142a4129b2..74895c490623 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p5.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p5.cpp
@@ -9,3 +9,5 @@ class B {
template <class T> friend class A<T>::Member;
};
+A<int> a;
+B b;
diff --git a/test/CXX/temp/temp.param/p14.cpp b/test/CXX/temp/temp.param/p14.cpp
index 07e6bfe40983..150e0ad636be 100644
--- a/test/CXX/temp/temp.param/p14.cpp
+++ b/test/CXX/temp/temp.param/p14.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// 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/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp b/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp
index 650501069cc5..a41b46ff5c9b 100644
--- a/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp
+++ b/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// XFAIL: *
// Note: we fail this test because we perform template instantiation
// at the end of the translation unit, so argument-dependent lookup
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
index 2bd1400faefb..33fb93bacfaf 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
@@ -4,8 +4,7 @@ namespace N {
template<class T> class X;
}
-// FIXME: this diagnostic is terrible (PR3844).
-template<> class X<int> { /* ... */ }; // expected-error {{unqualified-id}}
+template<> class X<int> { /* ... */ }; // expected-error {{non-template class 'X'}}
namespace N {
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
new file mode 100644
index 000000000000..900b0b309277
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
@@ -0,0 +1,33 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ void f(T&);
+
+ struct Inner;
+
+ static T static_var;
+};
+
+template<typename T>
+void X0<T>::f(T& t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+struct X0<T>::Inner {
+ T member;
+};
+
+template<typename T>
+T X0<T>::static_var = 1; // expected-error{{incompatible type}}
+
+extern template struct X0<void*>;
+template struct X0<void*>; // expected-note 2{{instantiation}}
+
+template struct X0<int>; // expected-note 4{{explicit instantiation definition is here}}
+
+extern template void X0<int>::f(int&); // expected-error{{follows explicit instantiation definition}}
+extern template struct X0<int>::Inner; // expected-error{{follows explicit instantiation definition}}
+extern template int X0<int>::static_var; // expected-error{{follows explicit instantiation definition}}
+extern template struct X0<int>; // expected-error{{follows explicit instantiation definition}}
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/test/CXX/temp/temp.spec/temp.explicit/p12.cpp
new file mode 100644
index 000000000000..fdf4393d4385
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p12.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+char* p = 0;
+template<class T> T g(T x = &p) { return x; }
+template int g<int>(int); // OK even though &p isn’t an int.
+
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
index 2bd781bbed28..9057971a5bb4 100644
--- a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
@@ -9,15 +9,13 @@ template void f0(int); // okay
// template shall be in scope at the point of the explicit instantiation of
// the member function template.
struct X0; // expected-note 2{{forward declaration}}
-template<typename> struct X1; // expected-note 2{{declared here}} \
- // expected-note 3{{forward declaration}}
+template<typename> struct X1; // expected-note 5{{declared here}}
// FIXME: Repeated diagnostics here!
template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \
- // expected-error{{invalid token after}}
-template void X1<int>::f0<int>(int); // expected-error{{implicit instantiation of undefined template}} \
- // expected-error{{incomplete type}} \\
- // expected-error{{invalid token}}
+ // expected-error{{does not refer}}
+template void X1<int>::f0<int>(int); // expected-error 2{{implicit instantiation of undefined template}} \
+ // expected-error{{does not refer}}
// A definition of a class template or class member template shall be in scope
// at the point of the explicit instantiation of the class template or class
@@ -37,10 +35,10 @@ template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation
// A definition of a class template shall be in scope at the point of an
// explicit instantiation of a member function or a static data member of the
// class template.
-template void X1<int>::f1(int); // expected-error{{incomplete type}} \
+template void X1<int>::f1(int); // expected-error{{undefined template}} \
// expected-error{{does not refer}}
-template int X1<int>::member; // expected-error{{incomplete type}} \
+template int X1<int>::member; // expected-error{{undefined template}} \
// expected-error{{does not refer}}
// A definition of a member class of a class template shall be in scope at the
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
new file mode 100644
index 000000000000..a992648d7c48
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N {
+ template<class T> class Y { // expected-note{{explicit instantiation refers here}}
+ void mf() { }
+ };
+}
+
+template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}
+
+// FIXME: This example from the standard is wrong; note posted to CWG reflector
+// on 10/27/2009
+using N::Y;
+template class Y<int>; // expected-error{{must occur in}}
+
+template class N::Y<char*>;
+template void N::Y<double>::mf();
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/test/CXX/temp/temp.spec/temp.explicit/p6.cpp
new file mode 100644
index 000000000000..763d679db7bb
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p6.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<class T> class Array { /* ... */ };
+template<class T> void sort(Array<T>& v) { }
+
+// instantiate sort(Array<int>&) - template-argument deduced
+template void sort<>(Array<int>&);
+
+template void sort(Array<long>&);
+
+template<typename T, typename U> void f0(T, U*) { }
+
+template void f0<int>(int, float*);
+template void f0<>(double, float*);
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p7.cpp b/test/CXX/temp/temp.spec/temp.explicit/p7.cpp
new file mode 100644
index 000000000000..ffd653dbaa4f
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p7.cpp
@@ -0,0 +1,36 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ struct MemberClass {
+ T member; // expected-error{{with function type}}
+ };
+
+ T* f0(T* ptr) {
+ return ptr + 1; // expected-error{{pointer to function}}
+ }
+
+ static T* static_member;
+};
+
+template<typename T>
+T* X0<T>::static_member = ((T*)0) + 1; // expected-error{{pointer to function}}
+
+template class X0<int>; // okay
+
+template class X0<int(int)>; // expected-note 3{{requested here}}
+
+// Specialize everything, so that the explicit instantiation does not trigger
+// any diagnostics.
+template<>
+struct X0<int(long)>::MemberClass { };
+
+typedef int int_long_func(long);
+template<>
+int_long_func *X0<int_long_func>::f0(int_long_func *) { return 0; }
+
+template<>
+int_long_func *X0<int(long)>::static_member;
+
+template class X0<int(long)>;
+
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/test/CXX/temp/temp.spec/temp.explicit/p8.cpp
new file mode 100644
index 000000000000..9a5bd3245c78
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p8.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ struct MemberClass;
+
+ T* f0(T* ptr);
+
+ static T* static_member;
+};
+
+template class X0<int>; // okay
+template class X0<int(int)>; // okay; nothing gets instantiated.
+
+template<typename T>
+struct X0<T>::MemberClass {
+ T member;
+};
+
+template<typename T>
+T* X0<T>::f0(T* ptr) {
+ return ptr + 1;
+}
+
+template<typename T>
+T* X0<T>::static_member = 0;
+
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
new file mode 100644
index 000000000000..59705d8a20e7
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
@@ -0,0 +1,66 @@
+// RUN: clang-cc -emit-llvm -std=c++0x -o - %s | FileCheck %s
+
+template<typename T>
+struct X0 {
+ void f(T &t) {
+ t = 0;
+ }
+
+ void g(T &t);
+
+ void h(T &t);
+
+ static T static_var;
+};
+
+template<typename T>
+inline void X0<T>::g(T & t) {
+ t = 0;
+}
+
+template<typename T>
+void X0<T>::h(T & t) {
+ t = 0;
+}
+
+template<typename T>
+T X0<T>::static_var = 0;
+
+extern template struct X0<int*>;
+
+int *&test(X0<int*> xi, int *ip) {
+ // CHECK: define available_externally void @_ZN2X0IPiE1fERS0_
+ xi.f(ip);
+ // CHECK: define available_externally void @_ZN2X0IPiE1gERS0_
+ xi.g(ip);
+ // CHECK: declare void @_ZN2X0IPiE1hERS0_
+ xi.h(ip);
+ return X0<int*>::static_var;
+}
+
+template<typename T>
+void f0(T& t) {
+ t = 0;
+}
+
+template<typename T>
+inline void f1(T& t) {
+ t = 0;
+}
+
+extern template void f0<>(int *&);
+extern template void f1<>(int *&);
+
+void test_f0(int *ip, float *fp) {
+ // CHECK: declare void @_Z2f0IPiEvRT_
+ f0(ip);
+ // CHECK: define linkonce_odr void @_Z2f0IPfEvRT_
+ f0(fp);
+}
+
+void test_f1(int *ip, float *fp) {
+ // CHECK: define available_externally void @_Z2f1IPiEvRT_
+ f1(ip);
+ // CHECK: define linkonce_odr void @_Z2f1IPfEvRT_
+ f1(fp);
+}
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
new file mode 100644
index 000000000000..a53113fb969e
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
@@ -0,0 +1,59 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+
+template<typename T>
+struct X0 {
+ void f(T &t) {
+ t = 1; // expected-error{{incompatible type}}
+ }
+
+ void g(T &t);
+
+ void h(T &t);
+
+ static T static_var;
+};
+
+template<typename T>
+inline void X0<T>::g(T & t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+void X0<T>::h(T & t) {
+ t = 1;
+}
+
+template<typename T>
+T X0<T>::static_var = 1;
+
+extern template struct X0<int*>;
+
+int *&test(X0<int*> xi, int *ip) {
+ xi.f(ip); // expected-note{{instantiation}}
+ xi.g(ip); // expected-note{{instantiation}}
+ xi.h(ip);
+ return X0<int*>::static_var;
+}
+
+template<typename T>
+void f0(T& t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+inline void f1(T& t) {
+ t = 1; // expected-error 2{{incompatible type}}
+}
+
+extern template void f0<>(int *&);
+extern template void f1<>(int *&);
+
+void test_f0(int *ip, float *fp) {
+ f0(ip);
+ f0(fp); // expected-note{{instantiation}}
+}
+
+void test_f1(int *ip, float *fp) {
+ f1(ip); // expected-note{{instantiation}}
+ f1(fp); // expected-note{{instantiation}}
+}
diff --git a/test/CodeCompletion/macros.c b/test/CodeCompletion/macros.c
new file mode 100644
index 000000000000..d5c1f8f17fce
--- /dev/null
+++ b/test/CodeCompletion/macros.c
@@ -0,0 +1,37 @@
+#define FOO
+#define BAR(X, Y) X, Y
+#define IDENTITY(X) X
+#define WIBBLE(...)
+
+enum Color {
+ Red, Green, Blue
+};
+
+struct Point {
+ float x, y, z;
+ enum Color color;
+};
+
+void test(struct Point *p) {
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:14 %s -o - | FileCheck -check-prefix=CC1 %s &&
+ switch (p->IDENTITY(color)) {
+ // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC2 %s &&
+ case
+ }
+ // CC1: color
+ // CC1: x
+ // CC1: y
+ // CC1: z
+ // CC1: BAR(<#X#>, <#Y#>)
+ // CC1: FOO
+ // CC1: IDENTITY(<#X#>)
+ // CC1: WIBBLE
+ // CC2: Blue
+ // CC2: Green
+ // CC2: Red
+ // CC2: BAR(<#X#>, <#Y#>)
+ // CC2: FOO
+ // CC2: IDENTITY(<#X#>)
+ // CC2: WIBBLE
+ // RUN: true
+}
diff --git a/test/CodeGen/2008-07-21-mixed-var-fn-decl.c b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
index c55c86b2fc6c..59a3f3884951 100644
--- a/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
+++ b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c
@@ -1,5 +1,8 @@
-// RUN: clang-cc -emit-llvm -o - %s | grep -e "@g[0-9] " | count 2
+// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s
int g0, f0();
int f1(), g1;
+// CHECK: @g0 = common global i32 0, align 4
+// CHECK: @g1 = common global i32 0, align 4
+
diff --git a/test/CodeGen/2008-07-29-override-alias-decl.c b/test/CodeGen/2008-07-29-override-alias-decl.c
index 4a36e0f13d5c..872950029618 100644
--- a/test/CodeGen/2008-07-29-override-alias-decl.c
+++ b/test/CodeGen/2008-07-29-override-alias-decl.c
@@ -1,7 +1,13 @@
-// RUN: clang-cc -emit-llvm -o - %s | grep -e "^@f" | count 1
+// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s
int x() { return 1; }
+// CHECK: %retval = alloca i32
+// CHECK: store i32 1, i32* %retval
+// CHECK: %0 = load i32* %retval
+// CHECK: ret i32 %0
+
+
int f() __attribute__((weak, alias("x")));
/* Test that we link to the alias correctly instead of making a new
@@ -10,3 +16,10 @@ int f();
int h() {
return f();
}
+
+// CHECK: %retval = alloca i32
+// CHECK: %call = call i32 (...)* @f()
+// CHECK: store i32 %call, i32* %retval
+// CHECK: %0 = load i32* %retval
+// CHECK: ret i32 %0
+
diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c
index 0d8dbdfb9d38..bd287ad0ee69 100644
--- a/test/CodeGen/asm-inout.c
+++ b/test/CodeGen/asm-inout.c
@@ -1,6 +1,6 @@
// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t &&
// RUN: grep "load i8\*\*\* %p.addr" %t | count 1
-// XFAIL
+// XFAIL: *
// PR3800
void f(void **p)
diff --git a/test/CodeGen/blocks-2.c b/test/CodeGen/blocks-2.c
index bc6c2b916abd..acbaafd95605 100644
--- a/test/CodeGen/blocks-2.c
+++ b/test/CodeGen/blocks-2.c
@@ -1,7 +1,7 @@
// RUN: clang-cc -g %s -emit-llvm -o %t -fblocks &&
// RUN: grep "func.start" %t | count 4
// 1 declaration, 1 bar, 1 test_block_dbg and 1 for the block.
-// XFAIL
+// XFAIL: *
static __inline__ __attribute__((always_inline)) int bar(int va, int vb) { return (va == vb); }
diff --git a/test/CodeGen/builtin-unwind-init.c b/test/CodeGen/builtin-unwind-init.c
index 49a016a304f0..56872f7434ee 100644
--- a/test/CodeGen/builtin-unwind-init.c
+++ b/test/CodeGen/builtin-unwind-init.c
@@ -1,4 +1,5 @@
-// RUN: clang-cc -emit-llvm < %s -o - | grep -F "llvm.eh.unwind.init"
+// RUN: clang-cc -emit-llvm < %s -o - | FileCheck %s
-int a() { __builtin_unwind_init(); }
+void a() { __builtin_unwind_init(); }
+// CHECK: call void @llvm.eh.unwind.init()
diff --git a/test/CodeGen/cast-to-union.c b/test/CodeGen/cast-to-union.c
index 674299294928..1f7e0457706d 100644
--- a/test/CodeGen/cast-to-union.c
+++ b/test/CodeGen/cast-to-union.c
@@ -1,5 +1,5 @@
// RUN: clang-cc -emit-llvm %s -o - | FileCheck %s
-// CHECK: w = global %0 { i32 2, [4 x i8] zeroinitializer }
+// CHECK: w = global %0 { i32 2, [4 x i8] undef }
// CHECK: y = global %union.u { double 7.300000e+0{{[0]*}}1 }
// CHECK: store i32 351, i32
diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c
index d2d3b031a83b..b09b28b8d93d 100644
--- a/test/CodeGen/function-attributes.c
+++ b/test/CodeGen/function-attributes.c
@@ -1,12 +1,12 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s &&
-// RUN: grep 'define signext i8 @f0(i32 %x) nounwind' %t &&
-// RUN: grep 'define zeroext i8 @f1(i32 %x) nounwind' %t &&
-// RUN: grep 'define void @f2(i8 signext %x) nounwind' %t &&
-// RUN: grep 'define void @f3(i8 zeroext %x) nounwind' %t &&
-// RUN: grep 'define signext i16 @f4(i32 %x) nounwind' %t &&
-// RUN: grep 'define zeroext i16 @f5(i32 %x) nounwind' %t &&
-// RUN: grep 'define void @f6(i16 signext %x) nounwind' %t &&
-// RUN: grep 'define void @f7(i16 zeroext %x) nounwind' %t &&
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -Os -o - %s | FileCheck %s
+// CHECK: define signext i8 @f0(i32 %x) nounwind
+// CHECK: define zeroext i8 @f1(i32 %x) nounwind
+// CHECK: define void @f2(i8 signext %x) nounwind
+// CHECK: define void @f3(i8 zeroext %x) nounwind
+// CHECK: define signext i16 @f4(i32 %x) nounwind
+// CHECK: define zeroext i16 @f5(i32 %x) nounwind
+// CHECK: define void @f6(i16 signext %x) nounwind
+// CHECK: define void @f7(i16 zeroext %x) nounwind
signed char f0(int x) { return x; }
@@ -24,15 +24,22 @@ void f6(signed short x) { }
void f7(unsigned short x) { }
-// RUN: grep 'define void @f8() nounwind alwaysinline' %t &&
+// CHECK: define void @f8()
+// CHECK: nounwind
+// CHECK: alwaysinline
+// CHECK: {
void __attribute__((always_inline)) f8(void) { }
-// RUN: grep 'call void @f9_t() noreturn' %t &&
+// CHECK: call void @f9_t()
+// CHECK: noreturn
+// CHECK: {
void __attribute__((noreturn)) f9_t(void);
void f9(void) { f9_t(); }
// FIXME: We should be setting nounwind on calls.
-// RUN: grep 'call i32 @f10_t() readnone' %t &&
+// CHECK: call i32 @f10_t()
+// CHECK: readnone
+// CHECK: {
int __attribute__((const)) f10_t(void);
int f10(void) { return f10_t(); }
int f11(void) {
@@ -43,13 +50,15 @@ int f12(int arg) {
return arg ? 0 : f10_t();
}
-// RUN: grep 'define void @f13() nounwind readnone' %t &&
+// CHECK: define void @f13() nounwind readnone
void f13(void) __attribute__((pure)) __attribute__((const));
void f13(void){}
// Ensure that these get inlined: rdar://6853279
-// RUN: not grep '@ai_' %t &&
+// CHECK: define void @f14
+// CHECK-NOT: @ai_
+// CHECK: call void @f14_end
static __inline__ __attribute__((always_inline))
int ai_1() { return 4; }
@@ -58,12 +67,17 @@ struct {
int a, b, c, d, e;
} ai_2() { while (1) {} }
-
-int foo() {
- ai_2();
- return ai_1();
+void f14(int a) {
+ extern void f14_end(void);
+ if (a)
+ ai_2();
+ ai_1();
+ f14_end();
}
-
-
-// RUN: true
+// <rdar://problem/7102668> [irgen] clang isn't setting the optsize bit on functions
+// CHECK: define void @f15
+// CHECK: optsize
+// CHECK: {
+void f15(void) {
+}
diff --git a/test/CodeGen/indirect-goto.c b/test/CodeGen/indirect-goto.c
index b9a601953877..6804f5739bbf 100644
--- a/test/CodeGen/indirect-goto.c
+++ b/test/CodeGen/indirect-goto.c
@@ -1,9 +1,7 @@
-// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t &&
-// RUN: grep "ret i32" %t | count 1 &&
-// RUN: grep "ret i32 210" %t | count 1
+// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts -S | grep "ret i32 2520"
static int foo(unsigned i) {
- const void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 };
+ void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 };
int res = 1;
goto *addrs[i];
@@ -15,6 +13,19 @@ static int foo(unsigned i) {
return res;
}
-int bar() {
- return foo(3);
+static int foo2(unsigned i) {
+ static const void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 };
+ int res = 1;
+
+ goto *addrs[i];
+L5: res *= 11;
+L4: res *= 7;
+L3: res *= 5;
+L2: res *= 3;
+L1: res *= 2;
+ return res;
+}
+
+int main() {
+ return foo(3)+foo2(4);
}
diff --git a/test/CodeGen/mangle.c b/test/CodeGen/mangle.c
index 17d74ba71f0c..6f42f6f6496c 100644
--- a/test/CodeGen/mangle.c
+++ b/test/CodeGen/mangle.c
@@ -1,22 +1,20 @@
-// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s &&
-// RUN: grep '@_Z2f0i' %t &&
-// RUN: grep '@_Z2f0l' %t &&
+// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s
-// Make sure we mangle overloadable, even in C system headers.
+// CHECK: @"\01foo"
+// Make sure we mangle overloadable, even in C system headers.
# 1 "somesystemheader.h" 1 3 4
+// CHECK: @_Z2f0i
void __attribute__((__overloadable__)) f0(int a) {}
+// CHECK: @_Z2f0l
void __attribute__((__overloadable__)) f0(long b) {}
-
+// CHECK: @"\01bar"
// These should get merged.
void foo() __asm__("bar");
void foo2() __asm__("bar");
-// RUN: grep '@"\\01foo"' %t &&
-// RUN: grep '@"\\01bar"' %t
-
int nux __asm__("foo");
extern float nux2 __asm__("foo");
@@ -52,3 +50,12 @@ void foo6() {
int foo7 __asm__("foo7") __attribute__((used));
float foo8 __asm__("foo7") = 42;
+
+// PR4412
+int func(void);
+extern int func (void) __asm__ ("FUNC");
+
+// CHECK: @"\01FUNC"
+int func(void) {
+ return 42;
+}
diff --git a/test/CodeGen/object-size.c b/test/CodeGen/object-size.c
new file mode 100644
index 000000000000..61d85419fc69
--- /dev/null
+++ b/test/CodeGen/object-size.c
@@ -0,0 +1,126 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o - | FileCheck %s
+
+#define strcpy(dest, src) \
+ ((__builtin_object_size(dest, 0) != -1ULL) \
+ ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \
+ : __inline_strcpy_chk(dest, src))
+
+static char *__inline_strcpy_chk (char *dest, const char *src) {
+ return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
+}
+
+char gbuf[63];
+char *gp;
+int gi, gj;
+
+void test1() {
+ // CHECK: movabsq $59, %rdx
+ // CHECK-NEXT: movq %rax, %rdi
+ // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: call ___strcpy_chk
+ strcpy(&gbuf[4], "Hi there");
+}
+
+void test2() {
+ // CHECK: movabsq $63, %rdx
+ // CHECK-NEXT: movq %rax, %rdi
+ // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: call ___strcpy_chk
+ strcpy(gbuf, "Hi there");
+}
+
+void test3() {
+ // CHECK: movabsq $0, %rdx
+ // CHECK-NEXT: movq %rax, %rdi
+ // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: call ___strcpy_chk
+ strcpy(&gbuf[100], "Hi there");
+}
+
+void test4() {
+ // CHECK: movabsq $0, %rdx
+ // CHECK-NEXT: movq %rax, %rdi
+ // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: call ___strcpy_chk
+ strcpy((char*)(void*)&gbuf[-1], "Hi there");
+}
+
+void test5() {
+ // CHECK: movb $0, %al
+ // CHECK-NEXT: testb %al, %al
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(gp, "Hi there");
+}
+
+void test6() {
+ char buf[57];
+
+ // CHECK: movabsq $53, %rdx
+ // CHECK-NEXT: movq %rax, %rdi
+ // CHECK-NEXT: movq %rcx, %rsi
+ // CHECK-NEXT: call ___strcpy_chk
+ strcpy(&buf[4], "Hi there");
+}
+
+void test7() {
+ int i;
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy((++i, gbuf), "Hi there");
+}
+
+void test8() {
+ char *buf[50];
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(buf[++gi], "Hi there");
+}
+
+void test9() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy((char *)((++gi) + gj), "Hi there");
+}
+
+char **p;
+void test10() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(*(++p), "Hi there");
+}
+
+void test11() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(gp = gbuf, "Hi there");
+}
+
+void test12() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(++gp, "Hi there");
+}
+
+void test13() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(gp++, "Hi there");
+}
+
+void test14() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(--gp, "Hi there");
+}
+
+void test15() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(gp--, "Hi there");
+}
+
+void test16() {
+ // CHECK-NOT: call ___strcpy_chk
+ // CHECK: call ___inline_strcpy_chk
+ strcpy(gp += 1, "Hi there");
+}
diff --git a/test/CodeGen/union-init2.c b/test/CodeGen/union-init2.c
index 184d75f47156..e782425cf2b1 100644
--- a/test/CodeGen/union-init2.c
+++ b/test/CodeGen/union-init2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -emit-llvm %s -o - -triple i686-pc-linux-gnu | grep "bitcast (%0\* @r to %union.x\*), \[4 x i8\] zeroinitializer"
+// RUN: clang-cc -emit-llvm %s -o - -triple i686-pc-linux-gnu | grep "bitcast (%0\* @r to %union.x\*), \[4 x i8\] undef"
// Make sure we generate something sane instead of a ptrtoint
union x {long long b;union x* a;} r = {.a = &r};
diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c
index 87cb5ff4eb4f..e17669008a39 100644
--- a/test/CodeGen/volatile.c
+++ b/test/CodeGen/volatile.c
@@ -1,8 +1,8 @@
// RUN: clang-cc -emit-llvm < %s -o %t &&
-// RUN: grep volatile %t | count 25 &&
+// RUN: grep volatile %t | count 29 &&
// RUN: grep memcpy %t | count 7
-// The number 25 comes from the current codegen for volatile loads;
+// The number 29 comes from the current codegen for volatile loads;
// if this number changes, it's not necessarily something wrong, but
// something has changed to affect volatile load/store codegen
@@ -38,6 +38,9 @@ volatile extv4 vVE;
volatile struct {int x;} aggFct(void);
+typedef volatile int volatile_int;
+volatile_int vtS;
+
int main() {
int i;
@@ -62,6 +65,7 @@ int main() {
i=VE.yx[1];
i=vVE.zy[1];
i = aggFct().x;
+ i=vtS;
// store
@@ -81,12 +85,14 @@ int main() {
vBF.x=i;
V[3]=i;
vV[3]=i;
+ vtS=i;
// other ops:
++S;
++vS;
i+=S;
i+=vS;
+ ++vtS;
(void)vF2;
vF2 = vF2;
vF2 = vF2 = vF2;
diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp
new file mode 100644
index 000000000000..b444221533d3
--- /dev/null
+++ b/test/CodeGenCXX/array-construction.cpp
@@ -0,0 +1,40 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
+// RUN: true
+
+extern "C" int printf(...);
+
+static int count;
+static float fcount;
+
+class xpto {
+public:
+ xpto() : i(count++), f(fcount++) {
+ printf("xpto::xpto()\n");
+ }
+ int i;
+ float f;
+
+/**
+ NYI
+ ~xpto() {
+ printf("xpto::~xpto()\n");
+ }
+*/
+};
+
+int main() {
+ xpto array[2][3][4];
+ for (int h = 0; h < 2; h++)
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 4; j++)
+ printf("array[%d][%d][%d] = {%d, %f}\n",
+ h, i, j, array[h][i][j].i, array[h][i][j].f);
+}
+
+// CHECK-LP64: call __ZN4xptoC1Ev
+
+// CHECK-LP32: call L__ZN4xptoC1Ev
+
diff --git a/test/CodeGenCXX/ptr-to-datamember.cpp b/test/CodeGenCXX/ptr-to-datamember.cpp
index eee03c060f91..a7b4cc2f7afb 100644
--- a/test/CodeGenCXX/ptr-to-datamember.cpp
+++ b/test/CodeGenCXX/ptr-to-datamember.cpp
@@ -51,6 +51,21 @@ void test_aggr_pdata(A& a1) {
pr(a1.*af);
}
+void test_aggr_pdata_1(A* pa) {
+ F A::* af = &A::Af;
+ pr(pa->*af);
+
+ (pa->*af).iF = 100;
+ (pa->*af).fF = 200.00;
+ printf(" %d %f\n", (pa->*af).iF, (pa->*af).fF);
+ pr(pa->*af);
+
+ (pa->*af).iF++;
+ (pa->*af).fF--;
+ --(pa->*af).fF;
+ pr(pa->*af);
+}
+
int main()
{
A a1;
@@ -67,4 +82,5 @@ int main()
printf("%d\n", &A::B1::V::iV);
printf("%d, %f, %f \n", a1.*pa, a1.*pf, a1.*pd);
test_aggr_pdata(a1);
+ test_aggr_pdata_1(&a1);
}
diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp
new file mode 100644
index 000000000000..1e396e976575
--- /dev/null
+++ b/test/CodeGenCXX/ptr-to-member-function.cpp
@@ -0,0 +1,53 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
+// RUN: true
+// 13.3.3.2 Ranking implicit conversion sequences
+
+extern "C" int printf(...);
+
+struct A {
+int Ai;
+};
+
+struct B : public A {
+ void bf() { printf("B::bf called\n"); }
+};
+
+struct C : public B { };
+
+// conversion of B::* to C::* is better than conversion of A::* to C::*
+typedef void (A::*pmfa)();
+typedef void (B::*pmfb)();
+typedef void (C::*pmfc)();
+
+struct X {
+ operator pmfa();
+ operator pmfb() {
+ return &B::bf;
+ }
+};
+
+
+void g(pmfc pm) {
+ C c;
+ (c.*pm)();
+}
+
+void test2(X x)
+{
+ g(x);
+}
+
+int main()
+{
+ X x;
+ test2(x);
+}
+
+// CHECK-LP64: call __ZN1XcvM1BFvvEEv
+// CHECK-LP64: call __Z1gM1CFvvE
+
+// CHECK-LP32: call L__ZN1XcvM1BFvvEEv
+// CHECK-LP32: call __Z1gM1CFvvE
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index d622193f5986..e9ed0f7690bc 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -53,9 +53,9 @@ struct D {
};
void f4() {
- // CHECK call void @_ZN1DC1Ev
- // CHECK call void @_ZN1DD1Ev
- // CHECK call void @_ZN1DD1Ev
+ // CHECK: call void @_ZN1DC1Ev
+ // CHECK: call void @_ZN1DD1Ev
+ // CHECK: call void @_ZN1DD1Ev
D()();
}
diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp
index 21fecac11e7b..7911940c6dab 100644
--- a/test/CodeGenCXX/virt.cpp
+++ b/test/CodeGenCXX/virt.cpp
@@ -91,6 +91,50 @@ int main() {
// CHECK-LP64: movl $1, 12(%rax)
// CHECK-LP64: movl $2, 8(%rax)
+// FIXME: This is the wrong thunk, but until these issues are fixed, better
+// than nothing.
+// CHECK-LP64: __ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev:
+// CHECK-LP64-NEXT:Leh_func_begin43:
+// CHECK-LP64-NEXT: subq $24, %rsp
+// CHECK-LP64-NEXT:Llabel43:
+// CHECK-LP64-NEXT: movq %rdi, %rax
+// CHECK-LP64-NEXT: movq %rax, 8(%rsp)
+// CHECK-LP64-NEXT: movq 8(%rsp), %rax
+// CHECK-LP64-NEXT: movq %rax, %rcx
+// CHECK-LP64-NEXT: movabsq $-16, %rdx
+// CHECK-LP64-NEXT: addq %rdx, %rcx
+// CHECK-LP64-NEXT: movq -16(%rax), %rax
+// CHECK-LP64-NEXT: movq -72(%rax), %rax
+// CHECK-LP64-NEXT: addq %rax, %rcx
+// CHECK-LP64-NEXT: movq %rcx, %rax
+// CHECK-LP64-NEXT: movq %rax, %rdi
+// CHECK-LP64-NEXT: call __ZTch0_v16_n32_N8test16_D4foo1Ev
+// CHECK-LP64-NEXT: movq %rax, 16(%rsp)
+// CHECK-LP64-NEXT: movq 16(%rsp), %rax
+// CHECK-LP64-NEXT: addq $24, %rsp
+// CHECK-LP64-NEXT: ret
+
+// CHECK-LP64: __ZTch0_v16_n32_N8test16_D4foo1Ev:
+// CHECK-LP64-NEXT:Leh_func_begin44:
+// CHECK-LP64-NEXT: subq $24, %rsp
+// CHECK-LP64-NEXT:Llabel44:
+// CHECK-LP64-NEXT: movq %rdi, %rax
+// CHECK-LP64-NEXT: movq %rax, 8(%rsp)
+// CHECK-LP64-NEXT: movq 8(%rsp), %rax
+// CHECK-LP64-NEXT: movq %rax, %rdi
+// CHECK-LP64-NEXT: call __ZN8test16_D4foo1Ev
+// CHECK-LP64-NEXT: movq %rax, %rcx
+// CHECK-LP64-NEXT: movabsq $16, %rdx
+// CHECK-LP64-NEXT: addq %rdx, %rcx
+// CHECK-LP64-NEXT: movq 16(%rax), %rax
+// CHECK-LP64-NEXT: movq -32(%rax), %rax
+// CHECK-LP64-NEXT: addq %rax, %rcx
+// CHECK-LP64-NEXT: movq %rcx, %rax
+// CHECK-LP64-NEXT: movq %rax, 16(%rsp)
+// CHECK-LP64-NEXT: movq 16(%rsp), %rax
+// CHECK-LP64-NEXT: addq $24, %rsp
+// CHECK-LP64-NEXT: ret
+
struct test12_A {
virtual void foo0() { }
virtual void foo();
@@ -306,10 +350,10 @@ struct test5_D : virtual test5_B1, virtual test5_B21, virtual test5_B31 {
// CHECK-LP32-NEXT: .long __ZN9test5_B227funcB22Ev
// CHECK-LP32-NEXT: .long __ZN9test5_B217funcB21Ev
// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32: .long 8
-// CHECK-LP32 .space 4
-// CHECK-LP32 .space 4 FIXME
-// CHECK-LP32: .long 4
+// CHECK-LP32-NEXT: .long 8
+// CHECK-LP32-NEXT: .space 4
+// CHECK-LP32-NEXT: .space 4
+// CHECK-LP32-NEXT: .long 4
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .long 4294967288
@@ -358,10 +402,10 @@ struct test5_D : virtual test5_B1, virtual test5_B21, virtual test5_B31 {
// CHECK-LP64-NEXT: .quad __ZN9test5_B227funcB22Ev
// CHECK-LP64-NEXT: .quad __ZN9test5_B217funcB21Ev
// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64: .quad 16
-// CHECK-LP64 .space 8
-// CHECK-LP64 .space 8
-// CHECK-LP64: .quad 8
+// CHECK-LP64-NEXT: .quad 16
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad 18446744073709551600
@@ -1049,6 +1093,151 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP32-NEXT: .long __ZN10test16_NV28foo_NV2bEv
+class test17_B1 {
+ virtual void foo() = 0;
+ virtual void bar() { }
+};
+
+class test17_B2 : public test17_B1 {
+ void foo() { }
+ virtual void bar() = 0;
+};
+
+class test17_D : public test17_B2 {
+ void bar() { }
+};
+
+
+// CHECK-LP64:__ZTV8test17_D:
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI8test17_D
+// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv
+// CHECK-LP64-NEXT: .quad __ZN8test17_D3barEv
+
+// CHECK-LP64:__ZTV9test17_B2:
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI9test17_B2
+// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv
+// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual
+
+// CHECK-LP64:__ZTV9test17_B1:
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI9test17_B1
+// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual
+// CHECK-LP64-NEXT: .quad __ZN9test17_B13barEv
+
+
+struct test18_NV1 {
+ virtual void fooNV1() { }
+virtual void foo_NV1() { }
+ int i;
+};
+
+struct test18_NV2 {
+ virtual test18_NV2& foo1() { return *this; }
+virtual void foo_NV2() { }
+virtual void foo_NV2b() { }
+ int i;
+};
+
+struct test18_B : public test18_NV1, test18_NV2 {
+ virtual test18_B& foo1() { return *this; }
+ virtual test18_B *foo2() { return 0; }
+ virtual test18_B *foo3() { return 0; }
+virtual void foo_B() { }
+ int i;
+};
+
+struct test18_B2 : test18_NV1, virtual test18_B {
+ virtual test18_B2& foo1() { return *this; }
+ virtual test18_B2 *foo2() { return 0; }
+virtual void foo_B2() { }
+ int i;
+};
+
+struct test18_D : test18_NV1, virtual test18_B2 {
+ virtual test18_D& foo1() { return *this; }
+};
+
+
+struct test19_VB1 { };
+struct test19_B1 : public virtual test19_VB1 {
+ virtual void fB1() { }
+ virtual void foB1B2() { }
+ virtual void foB1B3() { }
+ virtual void foB1B4() { }
+};
+
+struct test19_VB2 { };
+struct test19_B2: public test19_B1, public virtual test19_VB2 {
+ virtual void foB1B2() { }
+ virtual void foB1B3() { }
+ virtual void foB1B4() { }
+
+ virtual void fB2() { }
+ virtual void foB2B3() { }
+ virtual void foB2B4() { }
+};
+
+struct test19_VB3 { };
+struct test19_B3: virtual public test19_B2, public virtual test19_VB3 {
+ virtual void foB1B3() { }
+ virtual void foB1B4() { }
+
+ virtual void foB2B3() { }
+ virtual void foB2B4() { }
+
+ virtual void fB3() { }
+ virtual void foB3B4() { }
+};
+
+struct test19_VB4 { };
+struct test19_B4: public test19_B3, public virtual test19_VB4 {
+ virtual void foB1B4() { }
+
+ virtual void foB2B4() { }
+
+ virtual void foB3B4() { }
+
+ virtual void fB4() { }
+};
+
+struct test19_D : virtual test19_B4 {
+};
+
+
+// CHECK-LP64: __ZTV8test19_D:
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI8test19_D
+// CHECK-LP64-NEXT .quad __ZN9test19_B13fB1Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B26foB1B2Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B36foB1B3Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B46foB1B4Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B23fB2Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B36foB2B3Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B46foB2B4Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B33fB3Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B46foB3B4Ev
+// CHECK-LP64-NEXT .quad __ZN9test19_B43fB4Ev
+
+
+
// CHECK-LP64: __ZTV1B:
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad __ZTI1B
@@ -1127,6 +1316,9 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev
// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev
+test19_D d19;
+test18_D d18;
+test17_D d17;
test16_D d16;
test15_D d15;
test13_D d13;
diff --git a/test/CodeGenObjC/PR4894-recursive-debug-crash.m b/test/CodeGenObjC/PR4894-recursive-debug-crash.m
index c5f901c2680e..d7379111c11a 100644
--- a/test/CodeGenObjC/PR4894-recursive-debug-crash.m
+++ b/test/CodeGenObjC/PR4894-recursive-debug-crash.m
@@ -3,7 +3,7 @@
//
// This test is actually just making sure we can generate the debug info for the
// return type from im0 without crashing.
-// XFAIL
+// XFAIL: *
@interface I0 {
I0 *_iv0;
diff --git a/test/CodeGenObjC/encode-test-2.m b/test/CodeGenObjC/encode-test-2.m
index 6901168b1d09..07a53367557a 100644
--- a/test/CodeGenObjC/encode-test-2.m
+++ b/test/CodeGenObjC/encode-test-2.m
@@ -3,7 +3,7 @@
// RUN: grep -e "@\\\22<X><Y>\\\22" %t &&
// RUN: grep -e "@\\\22<X><Y><Z>\\\22" %t &&
// RUN: grep -e "@\\\22Foo<X><Y><Z>\\\22" %t &&
-// RUN: grep -e "{Intf=@@@@}" %t
+// RUN: grep -e "{Intf=@@@@#}" %t
@protocol X, Y, Z;
@class Foo;
@@ -17,6 +17,7 @@ id <X> IVAR_x;
id <X, Y> IVAR_xy;
id <X, Y, Z> IVAR_xyz;
Foo <X, Y, Z> *IVAR_Fooxyz;
+Class <X> IVAR_Classx;
}
@end
diff --git a/test/CodeGenObjC/synthesize_ivar.m b/test/CodeGenObjC/synthesize_ivar.m
index 7646f707bf76..e1746f1da136 100644
--- a/test/CodeGenObjC/synthesize_ivar.m
+++ b/test/CodeGenObjC/synthesize_ivar.m
@@ -1,8 +1,6 @@
// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
@interface I
-{
-}
@property int IP;
@end
@@ -25,3 +23,16 @@
@implementation OrganizerViolatorView
@synthesize bindingInfo;
@end
+
+// <rdar://problem/7336352> [irgen] crash in synthesized property construction
+
+@interface I0 @end
+@protocol P0 @end
+@interface I1 {
+ I0<P0> *iv0;
+}
+@property (assign, readwrite) id p0;
+@end
+@implementation I1
+@synthesize p0 = iv0;
+@end
diff --git a/test/Coverage/objc-language-features.inc b/test/Coverage/objc-language-features.inc
index dd57dfbedd03..dbbf205fcd6b 100644
--- a/test/Coverage/objc-language-features.inc
+++ b/test/Coverage/objc-language-features.inc
@@ -14,6 +14,7 @@
@interface A : Root <P1> {
int iv0;
B *iv1;
+ B<P1> *iv2;
}
@property(readonly) int p0;
@@ -21,11 +22,16 @@
@property(copy) id p2;
@property(retain) id p3;
@property(assign, getter=getme, setter=setme:) id p4;
+@property(assign, readwrite) id p5;
@end
@implementation A
@dynamic p0;
@synthesize p1 = iv0;
+
+// Property type can differ from ivar type.
+@synthesize p5 = iv2;
+
+(void) fm0 {
[super fm0];
}
diff --git a/test/Coverage/targets.c b/test/Coverage/targets.c
index 5a87b4dcc554..c4f030fff3d0 100644
--- a/test/Coverage/targets.c
+++ b/test/Coverage/targets.c
@@ -16,4 +16,8 @@
// RUN: clang-cc -g -triple x86_64-apple-darwin9 -emit-llvm -o %t %s &&
// RUN: clang-cc -g -triple x86_64-pc-linux-gnu -emit-llvm -o %t %s &&
// RUN: clang-cc -g -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
+
+// <rdar://problem/7181838> clang 1.0 fails to compile Python 2.6
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -mmacosx-version-min=10.4 &&
+
// RUN: true
diff --git a/test/Driver/analyze.c b/test/Driver/analyze.c
index 5ca890f9ab48..03810688d1f7 100644
--- a/test/Driver/analyze.c
+++ b/test/Driver/analyze.c
@@ -2,8 +2,8 @@
// (at least for a few key ones).
// RUN: env MACOSX_DEPLOYMENT_TARGET=10.5 clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log &&
-// RUN: grep '"-analyze"' %t.log &&
-// RUN: grep '"--fmath-errno=0"' %t.log &&
-// RUN: grep '"-target-feature" "+sse"' %t.log &&
-// RUN: grep '"-mmacosx-version-min=10.5"' %t.log
+// RUN: FileCheck --input-file=%t.log %s
+// CHECK: "-analyze"
+// CHECK: "-target-feature" "+sse"
+// CHECK: "--fmath-errno=0"
diff --git a/test/Driver/ccc-add-args.c b/test/Driver/ccc-add-args.c
index b504b0b42933..21e4471c1276 100644
--- a/test/Driver/ccc-add-args.c
+++ b/test/Driver/ccc-add-args.c
@@ -1,3 +1,3 @@
-// RUN: env CCC_ADD_ARGS="-ccc-echo,-ccc-print-options,,-v" clang -### 2> %t &&
-// RUN: grep -F 'Option 0 - Name: "-v", Values: {}' %t &&
-// RUN: grep -F 'Option 1 - Name: "-###", Values: {}' %t
+// RUN: env CCC_ADD_ARGS="-ccc-echo,-ccc-print-options,,-v" clang -### 2>&1 | FileCheck %s
+// CHECK: Option 0 - Name: "-v", Values: {}
+// CHECK: Option 1 - Name: "-###", Values: {}
diff --git a/test/Driver/hello.c b/test/Driver/hello.c
index 7dbe9c74f9c5..ead0d07b57ce 100644
--- a/test/Driver/hello.c
+++ b/test/Driver/hello.c
@@ -6,6 +6,10 @@
// RUN: %t > %t.out &&
// RUN: grep "I'm a little driver, short and stout." %t.out
+// FIXME: We don't have a usable assembler on Windows, so we can't build real
+// apps yet.
+// XFAIL: win32
+
#include <stdio.h>
int main() {
diff --git a/test/Driver/phases.c b/test/Driver/phases.c
index 0967d33816fe..61f68c452835 100644
--- a/test/Driver/phases.c
+++ b/test/Driver/phases.c
@@ -1,79 +1,79 @@
// Basic compilation for various types of files.
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c %s -x objective-c %s -x c++ %s -x objective-c++ -x assembler %s -x assembler-with-cpp %s -x none %s 2> %t &&
-// RUN: grep '0: input, ".*phases.c", c' %t &&
-// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t &&
-// RUN: grep -F '2: compiler, {1}, assembler' %t &&
-// RUN: grep -F '3: assembler, {2}, object' %t &&
-// RUN: grep '4: input, ".*phases.c", objective-c' %t &&
-// RUN: grep -F '5: preprocessor, {4}, objective-c-cpp-output' %t &&
-// RUN: grep -F '6: compiler, {5}, assembler' %t &&
-// RUN: grep -F '7: assembler, {6}, object' %t &&
-// RUN: grep '8: input, ".*phases.c", c++' %t &&
-// RUN: grep -F '9: preprocessor, {8}, c++-cpp-output' %t &&
-// RUN: grep -F '10: compiler, {9}, assembler' %t &&
-// RUN: grep -F '11: assembler, {10}, object' %t &&
-// RUN: grep '12: input, ".*phases.c", assembler' %t &&
-// RUN: grep -F '13: assembler, {12}, object' %t &&
-// RUN: grep '14: input, ".*phases.c", assembler-with-cpp' %t &&
-// RUN: grep -F '15: preprocessor, {14}, assembler' %t &&
-// RUN: grep -F '16: assembler, {15}, object' %t &&
-// RUN: grep '17: input, ".*phases.c", c' %t &&
-// RUN: grep -F '18: preprocessor, {17}, cpp-output' %t &&
-// RUN: grep -F '19: compiler, {18}, assembler' %t &&
-// RUN: grep -F '20: assembler, {19}, object' %t &&
-// RUN: grep -F '21: linker, {3, 7, 11, 13, 16, 20}, image' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c %s -x objective-c %s -x c++ %s -x objective-c++ -x assembler %s -x assembler-with-cpp %s -x none %s 2>&1 | FileCheck -check-prefix=BASIC %s &&
+// BASIC: 0: input, "{{.*}}phases.c", c
+// BASIC: 1: preprocessor, {0}, cpp-output
+// BASIC: 2: compiler, {1}, assembler
+// BASIC: 3: assembler, {2}, object
+// BASIC: 4: input, "{{.*}}phases.c", objective-c
+// BASIC: 5: preprocessor, {4}, objective-c-cpp-output
+// BASIC: 6: compiler, {5}, assembler
+// BASIC: 7: assembler, {6}, object
+// BASIC: 8: input, "{{.*}}phases.c", c++
+// BASIC: 9: preprocessor, {8}, c++-cpp-output
+// BASIC: 10: compiler, {9}, assembler
+// BASIC: 11: assembler, {10}, object
+// BASIC: 12: input, "{{.*}}phases.c", assembler
+// BASIC: 13: assembler, {12}, object
+// BASIC: 14: input, "{{.*}}phases.c", assembler-with-cpp
+// BASIC: 15: preprocessor, {14}, assembler
+// BASIC: 16: assembler, {15}, object
+// BASIC: 17: input, "{{.*}}phases.c", c
+// BASIC: 18: preprocessor, {17}, cpp-output
+// BASIC: 19: compiler, {18}, assembler
+// BASIC: 20: assembler, {19}, object
+// BASIC: 21: linker, {3, 7, 11, 13, 16, 20}, image
// Universal linked image.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2> %t &&
-// RUN: grep '0: input, ".*phases.c", c' %t &&
-// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t &&
-// RUN: grep -F '2: compiler, {1}, assembler' %t &&
-// RUN: grep -F '3: assembler, {2}, object' %t &&
-// RUN: grep -F '4: linker, {3}, image' %t &&
-// RUN: grep -F '5: bind-arch, "ppc", {4}, image' %t &&
-// RUN: grep -F '6: bind-arch, "i386", {4}, image' %t &&
-// RUN: grep -F '7: lipo, {5, 6}, image' %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=ULI %s &&
+// ULI: 0: input, "{{.*}}phases.c", c
+// ULI: 1: preprocessor, {0}, cpp-output
+// ULI: 2: compiler, {1}, assembler
+// ULI: 3: assembler, {2}, object
+// ULI: 4: linker, {3}, image
+// ULI: 5: bind-arch, "ppc", {4}, image
+// ULI: 6: bind-arch, "i386", {4}, image
+// ULI: 7: lipo, {5, 6}, image
// Universal object file.
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2> %t &&
-// RUN: grep '0: input, ".*phases.c", c' %t &&
-// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t &&
-// RUN: grep -F '2: compiler, {1}, assembler' %t &&
-// RUN: grep -F '3: assembler, {2}, object' %t &&
-// RUN: grep -F '4: bind-arch, "ppc", {3}, object' %t &&
-// RUN: grep -F '5: bind-arch, "i386", {3}, object' %t &&
-// RUN: grep -F '6: lipo, {4, 5}, object' %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2>&1 | FileCheck -check-prefix=UOF %s &&
+// UOF: 0: input, "{{.*}}phases.c", c
+// UOF: 1: preprocessor, {0}, cpp-output
+// UOF: 2: compiler, {1}, assembler
+// UOF: 3: assembler, {2}, object
+// UOF: 4: bind-arch, "ppc", {3}, object
+// UOF: 5: bind-arch, "i386", {3}, object
+// UOF: 6: lipo, {4, 5}, object
// Arch defaulting
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s 2> %t &&
-// RUN: grep -F '2: bind-arch, "i386", {1}, object' %t &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s -m32 -m64 2> %t &&
-// RUN: grep -F '2: bind-arch, "x86_64", {1}, object' %t &&
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s 2> %t &&
-// RUN: grep -F '2: bind-arch, "x86_64", {1}, object' %t &&
-// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s -m64 -m32 2> %t &&
-// RUN: grep -F '2: bind-arch, "i386", {1}, object' %t &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH1 %s &&
+// ARCH1: 2: bind-arch, "i386", {1}, object
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s -m32 -m64 2>&1 | FileCheck -check-prefix=ARCH2 %s &&
+// ARCH2: 2: bind-arch, "x86_64", {1}, object
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s 2>&1 | FileCheck -check-prefix=ARCH3 %s &&
+// ARCH3: 2: bind-arch, "x86_64", {1}, object
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s -m64 -m32 2>&1 | FileCheck -check-prefix=ARCH4 %s &&
+// ARCH4: 2: bind-arch, "i386", {1}, object
// Analyzer
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases --analyze %s 2> %t &&
-// RUN: grep '0: input, ".*phases.c", c' %t &&
-// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t &&
-// RUN: grep -F '2: analyzer, {1}, plist' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases --analyze %s 2>&1 | FileCheck -check-prefix=ANALYZE %s &&
+// ANALYZE: 0: input, "{{.*}}phases.c", c
+// ANALYZE: 1: preprocessor, {0}, cpp-output
+// ANALYZE: 2: analyzer, {1}, plist
// Precompiler
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c-header %s 2> %t &&
-// RUN: grep '0: input, ".*phases.c", c-header' %t &&
-// RUN: grep -F '1: preprocessor, {0}, c-header-cpp-output' %t &&
-// RUN: grep -F '2: precompiler, {1}, precompiled-header' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c-header %s 2>&1 | FileCheck -check-prefix=PCH %s &&
+// PCH: 0: input, "{{.*}}phases.c", c-header
+// PCH: 1: preprocessor, {0}, c-header-cpp-output
+// PCH: 2: precompiler, {1}, precompiled-header
// Darwin overrides the handling for .s
// RUN: touch %t.s &&
-// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.s 2> %t &&
-// RUN: grep '0: input, ".*\.s", assembler' %t &&
-// RUN: grep -F '1: assembler, {0}, object' %t &&
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c %t.s 2> %t &&
-// RUN: grep '0: input, ".*\.s", assembler-with-cpp' %t &&
-// RUN: grep -F '1: preprocessor, {0}, assembler' %t &&
-// RUN: grep -F '2: assembler, {1}, object' %t &&
+// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN1 %s &&
+// DARWIN1: 0: input, "{{.*}}.s", assembler
+// DARWIN1: 1: assembler, {0}, object
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c %t.s 2>&1 | FileCheck -check-prefix=DARWIN2 %s &&
+// DARWIN2: 0: input, "{{.*}}.s", assembler-with-cpp
+// DARWIN2: 1: preprocessor, {0}, assembler
+// DARWIN2: 2: assembler, {1}, object
// RUN: true
diff --git a/test/Driver/qa_override.c b/test/Driver/qa_override.c
index 46e150c74fdc..6f72078f12af 100644
--- a/test/Driver/qa_override.c
+++ b/test/Driver/qa_override.c
@@ -1,7 +1,5 @@
-// RUN: env QA_OVERRIDE_GCC3_OPTIONS="#+-Os +-Oz +-O +-O3 +-Oignore +a +b +c xb Xa Omagic ^-ccc-print-options " clang x -O2 b -O3 2> %t &&
-// RUN: grep '### ' %t | count 0 &&
-// RUN: grep -F 'Option 0 - Name: "<input>", Values: {"x"}' %t &&
-// RUN: grep -F 'Option 1 - Name: "-O", Values: {"ignore"}' %t &&
-// RUN: grep -F 'Option 2 - Name: "-O", Values: {"magic"}' %t &&
-// RUN: true
-
+// RUN: env QA_OVERRIDE_GCC3_OPTIONS="#+-Os +-Oz +-O +-O3 +-Oignore +a +b +c xb Xa Omagic ^-ccc-print-options " clang x -O2 b -O3 2>&1 | FileCheck %s
+// CHECK-NOT: ###
+// CHECK: Option 0 - Name: "<input>", Values: {"x"}
+// CHECK-NEXT: Option 1 - Name: "-O", Values: {"ignore"}
+// CHECK-NEXT: Option 2 - Name: "-O", Values: {"magic"}
diff --git a/test/Driver/std.c b/test/Driver/std.c
index ef6d8f197754..04113d5af134 100644
--- a/test/Driver/std.c
+++ b/test/Driver/std.c
@@ -1,8 +1,8 @@
-// RUN: clang -std=c99 -trigraphs -std=gnu99 %s -E -o %t &&
-// RUN: grep '??(??)' %t &&
-// RUN: clang -ansi %s -E -o %t &&
-// RUN: grep -F '[]' %t &&
-// RUN: clang -std=gnu99 -trigraphs %s -E -o %t &&
-// RUN: grep -F '[]' %t
+// RUN: clang -std=c99 -trigraphs -std=gnu99 %s -E -o - | FileCheck -check-prefix=OVERRIDE %s &&
+// OVERRIDE: ??(??)
+// RUN: clang -ansi %s -E -o - | FileCheck -check-prefix=ANSI %s &&
+// ANSI: []
+// RUN: clang -std=gnu99 -trigraphs %s -E -o - | FileCheck -check-prefix=EXPLICIT %s
+// EXPLICIT: []
??(??)
diff --git a/test/FixIt/fixit-pmem.cpp b/test/FixIt/fixit-pmem.cpp
new file mode 100644
index 000000000000..bb36f7fa9343
--- /dev/null
+++ b/test/FixIt/fixit-pmem.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ -
+
+/* This is a test of the various code modification hints that are
+ provided as part of warning or extension diagnostics. All of the
+ warnings will be fixed by -fixit, and the resulting file should
+ compile cleanly with -Werror -pedantic. */
+
+struct S {
+ int i;
+};
+
+int foo(int S::* ps, S s, S* p)
+{
+ p.*ps = 1;
+ return s->*ps;
+}
+
+void foo1(int (S::*ps)(), S s, S* p)
+{
+ (p.*ps)();
+ (s->*ps)();
+}
+
diff --git a/test/Frontend/darwin-version.c b/test/Frontend/darwin-version.c
index 513ea197e847..3217b9ad5e3b 100644
--- a/test/Frontend/darwin-version.c
+++ b/test/Frontend/darwin-version.c
@@ -1,23 +1,23 @@
-// RUN: clang-cc -triple armv6-apple-darwin9 -dM -E -o %t - < /dev/null &&
-// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '10000' | count 1 &&
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -dM -E -o %t %s &&
+// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '30000' | count 1 &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: clang-cc -triple armv6-apple-darwin9 -miphoneos-version-min=2.0 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.0 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20000' | count 1 &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 &&
-// RUN: clang-cc -triple armv6-apple-darwin9 -miphoneos-version-min=2.2 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple armv6-apple-darwin9 -miphoneos-version-min=2.2 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20200' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin8 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin8 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin9 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin10 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin10 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.4 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.4 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.5 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.5 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 &&
-// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.6 -dM -E -o %t - < /dev/null &&
+// RUN: clang -ccc-host-triple i686-apple-darwin9 -mmacosx-version-min=10.6 -dM -E -o %t %s &&
// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 &&
// RUN: true
diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c
index 4a1611aecff0..953869912bbb 100644
--- a/test/Frontend/dependency-gen.c
+++ b/test/Frontend/dependency-gen.c
@@ -1,7 +1,8 @@
// rdar://6533411
-// RUN: clang -MD -MF %t.d -c -x c -o %t.o /dev/null &&
+// RUN: clang -MD -MF %t.d -c -x c -o %t.o %s &&
// RUN: grep '.*dependency-gen.*:' %t.d &&
-// RUN: grep '/dev/null' %t.d &&
+// RUN: grep 'dependency-gen.c' %t.d &&
-// RUN: clang -M -x c /dev/null -o %t.deps &&
-// RUN: grep 'null.o: /dev/null' %t.deps
+// RUN: clang -M -x c %s -o %t.d &&
+// RUN: grep '.*dependency-gen.*:' %t.d &&
+// RUN: grep 'dependency-gen.c' %t.d
diff --git a/test/Lexer/block_cmt_end.c b/test/Lexer/block_cmt_end.c
index d85cf81f214a..83d6cf189243 100644
--- a/test/Lexer/block_cmt_end.c
+++ b/test/Lexer/block_cmt_end.c
@@ -17,7 +17,7 @@ next comment ends with normal escaped newline:
/* expected-warning {{escaped newline}} expected-warning {{backslash and newline}} *\
/
-int bar
+int bar /* expected-error {{invalid token after top level declarator}} */
/* xyz
@@ -26,7 +26,7 @@ next comment ends with a trigraph escaped newline: */
/* expected-warning {{escaped newline between}} expected-warning {{backslash and newline separated by space}} expected-warning {{trigraph ends block comment}} *??/
/
-foo /* expected-error {{invalid token after top level declarator}} */
+foo
// rdar://6060752 - We should not get warnings about trigraphs in comments:
diff --git a/test/Makefile b/test/Makefile
index 8543d431442b..fdb9d8f713d9 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -40,9 +40,10 @@ lit.site.cfg: FORCE
-e "s#@LLVM_LIBS_DIR@#$(LibDir)#g" \
-e "s#@CLANG_SOURCE_DIR@#$(PROJ_SRC_DIR)/..#g" \
-e "s#@CLANG_BINARY_DIR@#$(PROJ_OBJ_DIR)/..#g" \
+ -e "s#@TARGET_TRIPLE@#$(TARGET_TRIPLE)#g" \
$(PROJ_SRC_DIR)/lit.site.cfg.in > $@
clean::
- @ rm -rf Output/
+ @ find . -name Output | xargs rm -fr
.PHONY: all report clean
diff --git a/test/Misc/message-length.c b/test/Misc/message-length.c
index 9f4d66fe71c0..4502951dbf62 100644
--- a/test/Misc/message-length.c
+++ b/test/Misc/message-length.c
@@ -29,4 +29,4 @@ void a_very_long_line(int *ip, float *FloatPointer) {
// CHECK: FILE:23:78
-// CHECK: {{^ ...// some long comment text and a brace, eh {} $}}
+// CHECK: {{^ ...// some long comment text and a brace, eh {} }}
diff --git a/test/PCH/pr4489.c b/test/PCH/pr4489.c
index 7730819e9213..d05d5cd7ddab 100644
--- a/test/PCH/pr4489.c
+++ b/test/PCH/pr4489.c
@@ -1,5 +1,6 @@
// RUN: clang -x c-header -o %t.pch %s &&
-// RUN: clang -include %t -x c /dev/null -emit-llvm -S -o -
+// RUN: echo > %t.empty.c &&
+// RUN: clang -include %t -x c %t.empty.c -emit-llvm -S -o -
// PR 4489: Crash with PCH
// PR 4492: Crash with PCH (round two)
// PR 4509: Crash with PCH (round three)
@@ -37,4 +38,4 @@ void y1(void)
{
extern char e;
fprintf (0, "asdf");
-} \ No newline at end of file
+}
diff --git a/test/Parser/cxx-parse-member-pointer-op.cpp b/test/Parser/cxx-parse-member-pointer-op.cpp
new file mode 100644
index 000000000000..cc2e8b142fcb
--- /dev/null
+++ b/test/Parser/cxx-parse-member-pointer-op.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+struct C {};
+
+typedef void (C::*pmfc)();
+
+void g(pmfc) {
+ C *c;
+ c->*pmfc(); // expected-error {{invalid use of pointer to member type after '->*'}}
+ C c1;
+ c1.*pmfc(); // expected-error {{invalid use of pointer to member type after '.*'}}
+}
+
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index 9309b72a556e..2b2d3de50497 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -fms-extensions=0 %s
// Errors
export class foo { }; // expected-error {{expected template}}
@@ -92,3 +92,7 @@ void f2() {
int x;
A< typeof(x>1) > a;
}
+
+
+// PR3844
+template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}}
diff --git a/test/Preprocessor/assembler-with-cpp.c b/test/Preprocessor/assembler-with-cpp.c
index f7706ca676ce..4f1c443fc042 100644
--- a/test/Preprocessor/assembler-with-cpp.c
+++ b/test/Preprocessor/assembler-with-cpp.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=0 -E %s > %t &&
+// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=0 -E %s -o - | FileCheck -strict-whitespace -check-prefix=CHECK-Identifiers-False %s &&
#ifndef __ASSEMBLER__
#error "__ASSEMBLER__ not defined"
@@ -6,72 +6,70 @@
// Invalid token pasting is ok.
-// RUN: grep '1: X .' %t &&
#define A X ## .
1: A
+// CHECK-Identifiers-False: 1: X .
// Line markers are not linemarkers in .S files, they are passed through.
-// RUN: grep '# 321' %t &&
# 321
+// CHECK-Identifiers-False: # 321
// Unknown directives are passed through.
-// RUN: grep '# B C' %t &&
# B C
+// CHECK-Identifiers-False: # B C
// Unknown directives are expanded.
-// RUN: grep '# BAR42' %t &&
#define D(x) BAR ## x
# D(42)
+// CHECK-Identifiers-False: # BAR42
// Unmatched quotes are permitted.
-// RUN: grep "2: '" %t &&
-// RUN: grep '3: "' %t &&
2: '
3: "
+// CHECK-Identifiers-False: 2: '
+// CHECK-Identifiers-False: 3: "
// (balance quotes to keep editors happy): "'
// Empty char literals are ok.
-// RUN: grep "4: ''" %t &&
4: ''
+// CHECK-Identifiers-False: 4: ''
// Portions of invalid pasting should still expand as macros.
// rdar://6709206
-// RUN: grep "5: expanded (" %t &&
#define M4 expanded
#define M5() M4 ## (
5: M5()
+// CHECK-Identifiers-False: 5: expanded (
// rdar://6804322
-// RUN: grep -F "6: blarg $foo" %t &&
#define FOO(name) name ## $foo
6: FOO(blarg)
+// CHECK-Identifiers-False: 6: blarg $foo
-// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=1 -E %s > %t &&
-// RUN: grep -F "7: blarg$foo" %t &&
+// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=1 -E %s -o - | FileCheck -check-prefix=CHECK-Identifiers-True -strict-whitespace %s &&
#define FOO(name) name ## $foo
7: FOO(blarg)
-
+// CHECK-Identifiers-True: 7: blarg$foo
//
#define T6() T6 #nostring
#define T7(x) T7 #x
8: T6()
9: T7(foo)
-// RUN: grep '8: T6 #nostring' %t &&
-// RUN: grep '9: T7 "foo"' %t &&
+// CHECK-Identifiers-True: 8: T6 #nostring
+// CHECK-Identifiers-True: 9: T7 "foo"
// Concatenation with period doesn't leave a space
-// RUN: grep -F '10: .T8' %t &&
#define T8(A,B) A ## B
10: T8(.,T8)
-
+// CHECK-Identifiers-True: 10: .T8
// This should not crash.
-// RUN: grep '11: #0' %t &&
#define T11(a) #0
11: T11(b)
+// CHECK-Identifiers-True: 11: #0
// RUN: true
diff --git a/test/Preprocessor/c99-6_10_3_3_p4.c b/test/Preprocessor/c99-6_10_3_3_p4.c
index 89660549b9a1..99ad6e88a3f9 100644
--- a/test/Preprocessor/c99-6_10_3_3_p4.c
+++ b/test/Preprocessor/c99-6_10_3_3_p4.c
@@ -1,6 +1,10 @@
-// RUN: clang-cc -E %s | grep -F 'char p[] = "x ## y";'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
+
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
char p[] = join(x, y);
+
+// CHECK: char p[] = "x ## y";
+
diff --git a/test/Preprocessor/c99-6_10_3_4_p5.c b/test/Preprocessor/c99-6_10_3_4_p5.c
index 22bdf8258cbe..08b2c423601f 100644
--- a/test/Preprocessor/c99-6_10_3_4_p5.c
+++ b/test/Preprocessor/c99-6_10_3_4_p5.c
@@ -1,10 +1,5 @@
// Example from C99 6.10.3.4p5
-
-// RUN: clang-cc -E %s | grep -F 'f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);' &&
-// RUN: clang-cc -E %s | grep -F 'f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);' &&
-// RUN: clang-cc -E %s | grep -F 'int i[] = { 1, 23, 4, 5, };' &&
-// RUN: clang-cc -E %s | grep -F 'char c[2][6] = { "hello", "" };'
-
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define x 3
#define f(a) f(x * (a))
@@ -26,4 +21,8 @@
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
char c[2][6] = { str(hello), str() };
+// CHECK: f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+// CHECK: f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+// CHECK: int i[] = { 1, 23, 4, 5, };
+// CHECK: char c[2][6] = { "hello", "" };
diff --git a/test/Preprocessor/c99-6_10_3_4_p6.c b/test/Preprocessor/c99-6_10_3_4_p6.c
index c48d2efd2eff..8072d7b87bf2 100644
--- a/test/Preprocessor/c99-6_10_3_4_p6.c
+++ b/test/Preprocessor/c99-6_10_3_4_p6.c
@@ -1,10 +1,6 @@
// Example from C99 6.10.3.4p6
-// RUN: clang-cc -E %s | grep -F 'printf("x" "1" "= %d, x" "2" "= s" x1, x2);' &&
-// RUN: clang-cc -E %s | grep 'fputs("strncmp(\\"abc\\\\0d\\" \\"abc\\", .\\\\4.) == 0" ": @\\n", s);' &&
-// RUN: clang-cc -E %s | grep -F 'include "vers2.h"' &&
-// RUN: clang-cc -E %s | grep -F '"hello";' &&
-// RUN: clang-cc -E %s | grep -F '"hello" ", world"'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define str(s) # s
#define xstr(s) str(s)
@@ -22,3 +18,10 @@ include xstr(INCFILE(2).h)
glue(HIGH, LOW);
xglue(HIGH, LOW)
+
+// CHECK: printf("x" "1" "= %d, x" "2" "= s" x1, x2);
+// CHECK: fputs("strncmp(\"abc\\0d\" \"abc\", '\\4') == 0" ": @\n", s);
+// CHECK: include "vers2.h"
+// CHECK: "hello";
+// CHECK: "hello" ", world"
+
diff --git a/test/Preprocessor/c99-6_10_3_4_p7.c b/test/Preprocessor/c99-6_10_3_4_p7.c
index a53df8263f19..6a7eb48173b8 100644
--- a/test/Preprocessor/c99-6_10_3_4_p7.c
+++ b/test/Preprocessor/c99-6_10_3_4_p7.c
@@ -1,9 +1,10 @@
// Example from C99 6.10.3.4p7
-// RUN: clang-cc -E %s | grep -F 'int j[] = { 123, 45, 67, 89,' &&
-// RUN: clang-cc -E %s | grep -F '10, 11, 12, };'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define t(x,y,z) x ## y ## z
int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
t(10,,), t(,11,), t(,,12), t(,,) };
+// CHECK: int j[] = { 123, 45, 67, 89,
+// CHECK: 10, 11, 12, };
diff --git a/test/Preprocessor/c99-6_10_3_4_p9.c b/test/Preprocessor/c99-6_10_3_4_p9.c
index 39c34546ad4d..704241e46e3f 100644
--- a/test/Preprocessor/c99-6_10_3_4_p9.c
+++ b/test/Preprocessor/c99-6_10_3_4_p9.c
@@ -1,16 +1,20 @@
// Example from C99 6.10.3.4p9
-// RUN: clang-cc -E %s | grep -F 'fprintf(stderr, "Flag");' &&
-// RUN: clang-cc -E %s | grep -F 'fprintf(stderr, "X = %d\n", x);' &&
-// RUN: clang-cc -E %s | grep -F 'puts("The first, second, and third items.");' &&
-// RUN: clang-cc -E %s | grep -F '((x>y)?puts("x>y"): printf("x is %d but y is %d", x, y));'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define showlist(...) puts(#__VA_ARGS__)
#define report(test, ...) ((test)?puts(#test):\
printf(__VA_ARGS__))
-debug("Flag");
-debug("X = %d\n", x);
-showlist(The first, second, and third items.);
-report(x>y, "x is %d but y is %d", x, y);
+debug("Flag");
+// CHECK: fprintf(stderr, "Flag");
+
+debug("X = %d\n", x);
+// CHECK: fprintf(stderr, "X = %d\n", x);
+
+showlist(The first, second, and third items.);
+// CHECK: puts("The first, second, and third items.");
+
+report(x>y, "x is %d but y is %d", x, y);
+// CHECK: ((x>y)?puts("x>y"): printf("x is %d but y is %d", x, y));
diff --git a/test/Preprocessor/comment_save.c b/test/Preprocessor/comment_save.c
index 30b043433c97..ae609b117e7e 100644
--- a/test/Preprocessor/comment_save.c
+++ b/test/Preprocessor/comment_save.c
@@ -1,7 +1,8 @@
-// RUN: clang-cc -E -C %s | grep '^// foo$' &&
-// RUN: clang-cc -E -C %s | grep -F '^/* bar */$'
+// RUN: clang-cc -E -C %s | FileCheck -strict-whitespace %s
// foo
-/* bar */
+// CHECK: // foo
+/* bar */
+// CHECK: /* bar */
diff --git a/test/Preprocessor/comment_save_macro.c b/test/Preprocessor/comment_save_macro.c
index 66b59d136d73..b9a25ed2e7f3 100644
--- a/test/Preprocessor/comment_save_macro.c
+++ b/test/Preprocessor/comment_save_macro.c
@@ -1,6 +1,11 @@
-// RUN: clang-cc -E -C %s | grep '^boo bork bar // zot$' &&
-// RUN: clang-cc -E -CC %s | grep -F '^boo bork /* blah*/ bar // zot$' &&
-// RUN: clang-cc -E %s | grep '^boo bork bar$'
+// RUN: clang-cc -E -C %s | FileCheck -check-prefix=CHECK-C -strict-whitespace %s &&
+// CHECK-C: boo bork bar // zot
+
+// RUN: clang-cc -E -CC %s | FileCheck -check-prefix=CHECK-CC -strict-whitespace %s &&
+// CHECK-CC: boo bork /* blah*/ bar // zot
+
+// RUN: clang-cc -E %s | FileCheck -check-prefix=CHECK -strict-whitespace %s
+// CHECK: boo bork bar
#define FOO bork // blah
diff --git a/test/Preprocessor/has_include.c b/test/Preprocessor/has_include.c
new file mode 100644
index 000000000000..40697c099f4f
--- /dev/null
+++ b/test/Preprocessor/has_include.c
@@ -0,0 +1,83 @@
+// RUN: clang-cc -Eonly -verify %s
+
+// Try different path permutations of __has_include with existing file.
+#if __has_include("stdio.h")
+#else
+ #error "__has_include failed (1)."
+#endif
+
+#if __has_include(<stdio.h>)
+#else
+ #error "__has_include failed (2)."
+#endif
+
+// Try unary expression.
+#if !__has_include("stdio.h")
+ #error "__has_include failed (5)."
+#endif
+
+// Try binary expression.
+#if __has_include("stdio.h") && __has_include("stddef.h")
+#else
+ #error "__has_include failed (6)."
+#endif
+
+// Try non-existing file.
+#if __has_include("blahblah.h")
+ #error "__has_include failed (7)."
+#endif
+
+// Try defined.
+#if !defined(__has_include)
+ #error "defined(__has_include) failed (8)."
+#endif
+
+// Try different path permutations of __has_include_next with existing file.
+#if __has_include_next("stddef.h") // expected-warning {{#include_next in primary source file}}
+#else
+ #error "__has_include failed (1)."
+#endif
+
+#if __has_include_next(<stddef.h>) // expected-warning {{#include_next in primary source file}}
+#else
+ #error "__has_include failed (2)."
+#endif
+
+// Try unary expression.
+#if !__has_include_next("stdio.h") // expected-warning {{#include_next in primary source file}}
+ #error "__has_include_next failed (5)."
+#endif
+
+// Try binary expression.
+#if __has_include_next("stdio.h") && __has_include("stddef.h") // expected-warning {{#include_next in primary source file}}
+#else
+ #error "__has_include_next failed (6)."
+#endif
+
+// Try non-existing file.
+#if __has_include_next("blahblah.h") // expected-warning {{#include_next in primary source file}}
+ #error "__has_include_next failed (7)."
+#endif
+
+// Try defined.
+#if !defined(__has_include_next)
+ #error "defined(__has_include_next) failed (8)."
+#endif
+
+// Try badly formed expressions.
+// FIXME: I don't quite know how to avoid preprocessor side effects.
+// Use FileCheck?
+// It also assert due to unterminated #if's.
+//#if __has_include("stdio.h"
+//#if __has_include "stdio.h")
+//#if __has_include(stdio.h)
+//#if __has_include()
+//#if __has_include(
+//#if __has_include)
+//#if __has_include
+//#if __has_include(<stdio.h>
+//#if __has_include<stdio.h>)
+//#if __has_include("stdio.h)
+//#if __has_include(stdio.h")
+//#if __has_include(<stdio.h)
+//#if __has_include(stdio.h>)
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
new file mode 100644
index 000000000000..800b7506f4c2
--- /dev/null
+++ b/test/Preprocessor/init.c
@@ -0,0 +1,945 @@
+// RUN: clang-cc -E -dM -x=assembler-with-cpp < /dev/null | FileCheck -check-prefix ASM %s &&
+//
+// ASM:#define __ASSEMBLER__ 1
+//
+//
+// RUN: clang-cc -fblocks -E -dM < /dev/null | FileCheck -check-prefix BLOCKS %s &&
+//
+// BLOCKS:#define __BLOCKS__ 1
+// BLOCKS:#define __block __attribute__((__blocks__(byref)))
+//
+//
+// RUN: clang-cc -x=c++ -std=c++0x -E -dM < /dev/null | FileCheck -check-prefix CXX0X %s &&
+//
+// CXX0X:#define _GNU_SOURCE 1
+// CXX0X:#define __DEPRECATED 1
+// CXX0X:#define __GNUG__
+// CXX0X:#define __GXX_EXPERIMENTAL_CXX0X__ 1
+// CXX0X:#define __GXX_WEAK__ 1
+// CXX0X:#define __cplusplus 199711L
+// CXX0X:#define __private_extern__ extern
+//
+//
+// RUN: clang-cc -x=c++ -std=c++98 -E -dM < /dev/null | FileCheck -check-prefix CXX98 %s &&
+//
+// CXX98:#define _GNU_SOURCE 1
+// CXX98:#define __DEPRECATED 1
+// CXX98:#define __GNUG__
+// CXX98:#define __GXX_WEAK__ 1
+// CXX98:#define __cplusplus 199711L
+// CXX98:#define __private_extern__ extern
+//
+//
+// RUN: clang-cc -std=c99 -E -dM < /dev/null | FileCheck -check-prefix C99 %s &&
+//
+// C99:#define __STDC_VERSION__ 199901L
+// C99:#define __STRICT_ANSI__ 1
+//
+//
+// RUN: clang-cc -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix COMMON %s &&
+//
+// COMMON:#define __CONSTANT_CFSTRINGS__ 1
+// COMMON:#define __FINITE_MATH_ONLY__ 0
+// COMMON:#define __GNUC_MINOR__
+// COMMON:#define __GNUC_PATCHLEVEL__
+// COMMON:#define __GNUC_STDC_INLINE__ 1
+// COMMON:#define __GNUC__
+// COMMON:#define __GXX_ABI_VERSION
+// COMMON:#define __STDC_HOSTED__ 1
+// COMMON:#define __STDC_VERSION__
+// COMMON:#define __STDC__ 1
+// COMMON:#define __VERSION__
+// COMMON:#define __clang__ 1
+// COMMON:#define __llvm__ 1
+//
+//
+// RUN: clang-cc -ffreestanding -E -dM < /dev/null | FileCheck -check-prefix FREESTANDING %s &&
+// FREESTANDING:#define __STDC_HOSTED__ 0
+//
+// RUN: clang-cc -x=c++ -std=gnu++98 -E -dM < /dev/null | FileCheck -check-prefix GXX98 %s &&
+//
+// GXX98:#define _GNU_SOURCE 1
+// GXX98:#define __DEPRECATED 1
+// GXX98:#define __GNUG__
+// GXX98:#define __GXX_WEAK__ 1
+// GXX98:#define __cplusplus 1
+// GXX98:#define __private_extern__ extern
+//
+//
+// RUN: clang-cc -std=iso9899:199409 -E -dM < /dev/null | FileCheck -check-prefix C94 %s &&
+//
+// C94:#define __STDC_VERSION__ 199409L
+//
+//
+// RUN: clang-cc -fms-extensions -E -dM < /dev/null | FileCheck -check-prefix MSEXT %s &&
+//
+// MSEXT-NOT:#define __STDC__
+// MSEXT:#define __int16 __INT16_TYPE__
+// MSEXT:#define __int32 __INT32_TYPE__
+// MSEXT:#define __int64 __INT64_TYPE__
+// MSEXT:#define __int8 __INT8_TYPE__
+//
+//
+// RUN: clang-cc -x=objective-c -E -dM < /dev/null | FileCheck -check-prefix OBJC %s &&
+//
+// OBJC:#define OBJC_NEW_PROPERTIES 1
+// OBJC:#define __OBJC__ 1
+//
+//
+// RUN: clang-cc -x=objective-c -fobjc-gc -E -dM < /dev/null | FileCheck -check-prefix OBJCGC %s &&
+//
+// OBJCGC:#define __OBJC_GC__ 1
+//
+//
+// RUN: clang-cc -x=objective-c -fnext-runtime -E -dM < /dev/null | FileCheck -check-prefix NEXTRT %s &&
+//
+// NEXTRT:#define __NEXT_RUNTIME__ 1
+//
+//
+// RUN: clang-cc -x=objective-c -fobjc-nonfragile-abi -E -dM < /dev/null | FileCheck -check-prefix NONFRAGILE %s &&
+//
+// NONFRAGILE:#define OBJC_ZEROCOST_EXCEPTIONS 1
+// NONFRAGILE:#define __OBJC2__ 1
+//
+//
+// RUN: clang-cc -O1 -E -dM < /dev/null | FileCheck -check-prefix O1 %s &&
+//
+// O1:#define __OPTIMIZE__ 1
+//
+//
+// RUN: clang-cc -fpascal-strings -E -dM < /dev/null | FileCheck -check-prefix PASCAL %s &&
+//
+// PASCAL:#define __PASCAL_STRINGS__ 1
+//
+//
+// RUN: clang-cc -fsigned-char -E -dM -fms-extensions=0 < /dev/null | FileCheck -check-prefix SCHAR %s &&
+//
+// SCHAR:#define __STDC__ 1
+// SCHAR-NOT:#define __UNSIGNED_CHAR__
+// SCHAR:#define __clang__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -check-prefix ARM %s &&
+//
+// ARM:#define __APCS_32__ 1
+// ARM:#define __ARMEL__ 1
+// ARM:#define __ARM_ARCH_6K__ 1
+// ARM:#define __CHAR_BIT__ 8
+// ARM:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// ARM:#define __DBL_DIG__ 15
+// ARM:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// ARM:#define __DBL_HAS_DENORM__ 1
+// ARM:#define __DBL_HAS_INFINITY__ 1
+// ARM:#define __DBL_HAS_QUIET_NAN__ 1
+// ARM:#define __DBL_MANT_DIG__ 53
+// ARM:#define __DBL_MAX_10_EXP__ 308
+// ARM:#define __DBL_MAX_EXP__ 1024
+// ARM:#define __DBL_MAX__ 1.7976931348623157e+308
+// ARM:#define __DBL_MIN_10_EXP__ (-307)
+// ARM:#define __DBL_MIN_EXP__ (-1021)
+// ARM:#define __DBL_MIN__ 2.2250738585072014e-308
+// ARM:#define __DECIMAL_DIG__ 17
+// ARM:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// ARM:#define __FLT_DIG__ 6
+// ARM:#define __FLT_EPSILON__ 1.19209290e-7F
+// ARM:#define __FLT_EVAL_METHOD__ 0
+// ARM:#define __FLT_HAS_DENORM__ 1
+// ARM:#define __FLT_HAS_INFINITY__ 1
+// ARM:#define __FLT_HAS_QUIET_NAN__ 1
+// ARM:#define __FLT_MANT_DIG__ 24
+// ARM:#define __FLT_MAX_10_EXP__ 38
+// ARM:#define __FLT_MAX_EXP__ 128
+// ARM:#define __FLT_MAX__ 3.40282347e+38F
+// ARM:#define __FLT_MIN_10_EXP__ (-37)
+// ARM:#define __FLT_MIN_EXP__ (-125)
+// ARM:#define __FLT_MIN__ 1.17549435e-38F
+// ARM:#define __FLT_RADIX__ 2
+// ARM:#define __INT16_TYPE__ short
+// ARM:#define __INT32_TYPE__ int
+// ARM:#define __INT64_TYPE__ long long int
+// ARM:#define __INT8_TYPE__ char
+// ARM:#define __INTMAX_MAX__ 9223372036854775807LL
+// ARM:#define __INTMAX_TYPE__ long long int
+// ARM:#define __INTPTR_TYPE__ long int
+// ARM:#define __INT_MAX__ 2147483647
+// ARM:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// ARM:#define __LDBL_DIG__ 15
+// ARM:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// ARM:#define __LDBL_HAS_DENORM__ 1
+// ARM:#define __LDBL_HAS_INFINITY__ 1
+// ARM:#define __LDBL_HAS_QUIET_NAN__ 1
+// ARM:#define __LDBL_MANT_DIG__ 53
+// ARM:#define __LDBL_MAX_10_EXP__ 308
+// ARM:#define __LDBL_MAX_EXP__ 1024
+// ARM:#define __LDBL_MAX__ 1.7976931348623157e+308
+// ARM:#define __LDBL_MIN_10_EXP__ (-307)
+// ARM:#define __LDBL_MIN_EXP__ (-1021)
+// ARM:#define __LDBL_MIN__ 2.2250738585072014e-308
+// ARM:#define __LITTLE_ENDIAN__ 1
+// ARM:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// ARM:#define __LONG_MAX__ 2147483647L
+// ARM:#define __NO_INLINE__ 1
+// ARM:#define __POINTER_WIDTH__ 32
+// ARM:#define __PTRDIFF_TYPE__ int
+// ARM:#define __SCHAR_MAX__ 127
+// ARM:#define __SHRT_MAX__ 32767
+// ARM:#define __SIZE_TYPE__ unsigned int
+// ARM:#define __THUMB_INTERWORK__ 1
+// ARM:#define __UINTMAX_TYPE__ long long unsigned int
+// ARM:#define __USER_LABEL_PREFIX__ _
+// ARM:#define __VFP_FP__ 1
+// ARM:#define __WCHAR_MAX__ 2147483647
+// ARM:#define __WCHAR_TYPE__ int
+// ARM:#define __WINT_TYPE__ int
+// ARM:#define __arm 1
+// ARM:#define __arm__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=bfin-none-none < /dev/null | FileCheck -check-prefix BFIN %s &&
+//
+// BFIN:#define BFIN 1
+// BFIN:#define __ADSPBLACKFIN__ 1
+// BFIN:#define __ADSPLPBLACKFIN__ 1
+// BFIN:#define __BFIN 1
+// BFIN:#define __BFIN__ 1
+// BFIN:#define __CHAR_BIT__ 8
+// BFIN:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// BFIN:#define __DBL_DIG__ 15
+// BFIN:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// BFIN:#define __DBL_HAS_DENORM__ 1
+// BFIN:#define __DBL_HAS_INFINITY__ 1
+// BFIN:#define __DBL_HAS_QUIET_NAN__ 1
+// BFIN:#define __DBL_MANT_DIG__ 53
+// BFIN:#define __DBL_MAX_10_EXP__ 308
+// BFIN:#define __DBL_MAX_EXP__ 1024
+// BFIN:#define __DBL_MAX__ 1.7976931348623157e+308
+// BFIN:#define __DBL_MIN_10_EXP__ (-307)
+// BFIN:#define __DBL_MIN_EXP__ (-1021)
+// BFIN:#define __DBL_MIN__ 2.2250738585072014e-308
+// BFIN:#define __DECIMAL_DIG__ 17
+// BFIN:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// BFIN:#define __FLT_DIG__ 6
+// BFIN:#define __FLT_EPSILON__ 1.19209290e-7F
+// BFIN:#define __FLT_EVAL_METHOD__ 0
+// BFIN:#define __FLT_HAS_DENORM__ 1
+// BFIN:#define __FLT_HAS_INFINITY__ 1
+// BFIN:#define __FLT_HAS_QUIET_NAN__ 1
+// BFIN:#define __FLT_MANT_DIG__ 24
+// BFIN:#define __FLT_MAX_10_EXP__ 38
+// BFIN:#define __FLT_MAX_EXP__ 128
+// BFIN:#define __FLT_MAX__ 3.40282347e+38F
+// BFIN:#define __FLT_MIN_10_EXP__ (-37)
+// BFIN:#define __FLT_MIN_EXP__ (-125)
+// BFIN:#define __FLT_MIN__ 1.17549435e-38F
+// BFIN:#define __FLT_RADIX__ 2
+// BFIN:#define __INT16_TYPE__ short
+// BFIN:#define __INT32_TYPE__ int
+// BFIN:#define __INT64_TYPE__ long long int
+// BFIN:#define __INT8_TYPE__ char
+// BFIN:#define __INTMAX_MAX__ 9223372036854775807LL
+// BFIN:#define __INTMAX_TYPE__ long long int
+// BFIN:#define __INTPTR_TYPE__ long int
+// BFIN:#define __INT_MAX__ 2147483647
+// BFIN:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// BFIN:#define __LDBL_DIG__ 15
+// BFIN:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// BFIN:#define __LDBL_HAS_DENORM__ 1
+// BFIN:#define __LDBL_HAS_INFINITY__ 1
+// BFIN:#define __LDBL_HAS_QUIET_NAN__ 1
+// BFIN:#define __LDBL_MANT_DIG__ 53
+// BFIN:#define __LDBL_MAX_10_EXP__ 308
+// BFIN:#define __LDBL_MAX_EXP__ 1024
+// BFIN:#define __LDBL_MAX__ 1.7976931348623157e+308
+// BFIN:#define __LDBL_MIN_10_EXP__ (-307)
+// BFIN:#define __LDBL_MIN_EXP__ (-1021)
+// BFIN:#define __LDBL_MIN__ 2.2250738585072014e-308
+// BFIN:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// BFIN:#define __LONG_MAX__ 2147483647L
+// BFIN:#define __NO_INLINE__ 1
+// BFIN:#define __POINTER_WIDTH__ 32
+// BFIN:#define __PTRDIFF_TYPE__ long int
+// BFIN:#define __SCHAR_MAX__ 127
+// BFIN:#define __SHRT_MAX__ 32767
+// BFIN:#define __SIZE_TYPE__ long unsigned int
+// BFIN:#define __UINTMAX_TYPE__ long long unsigned int
+// BFIN:#define __USER_LABEL_PREFIX__ _
+// BFIN:#define __WCHAR_MAX__ 2147483647
+// BFIN:#define __WCHAR_TYPE__ int
+// BFIN:#define __WINT_TYPE__ int
+// BFIN:#define __bfin 1
+// BFIN:#define __bfin__ 1
+// BFIN:#define bfin 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=i386-none-none < /dev/null | FileCheck -check-prefix I386 %s &&
+//
+// I386:#define __CHAR_BIT__ 8
+// I386:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// I386:#define __DBL_DIG__ 15
+// I386:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// I386:#define __DBL_HAS_DENORM__ 1
+// I386:#define __DBL_HAS_INFINITY__ 1
+// I386:#define __DBL_HAS_QUIET_NAN__ 1
+// I386:#define __DBL_MANT_DIG__ 53
+// I386:#define __DBL_MAX_10_EXP__ 308
+// I386:#define __DBL_MAX_EXP__ 1024
+// I386:#define __DBL_MAX__ 1.7976931348623157e+308
+// I386:#define __DBL_MIN_10_EXP__ (-307)
+// I386:#define __DBL_MIN_EXP__ (-1021)
+// I386:#define __DBL_MIN__ 2.2250738585072014e-308
+// I386:#define __DECIMAL_DIG__ 21
+// I386:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// I386:#define __FLT_DIG__ 6
+// I386:#define __FLT_EPSILON__ 1.19209290e-7F
+// I386:#define __FLT_EVAL_METHOD__ 0
+// I386:#define __FLT_HAS_DENORM__ 1
+// I386:#define __FLT_HAS_INFINITY__ 1
+// I386:#define __FLT_HAS_QUIET_NAN__ 1
+// I386:#define __FLT_MANT_DIG__ 24
+// I386:#define __FLT_MAX_10_EXP__ 38
+// I386:#define __FLT_MAX_EXP__ 128
+// I386:#define __FLT_MAX__ 3.40282347e+38F
+// I386:#define __FLT_MIN_10_EXP__ (-37)
+// I386:#define __FLT_MIN_EXP__ (-125)
+// I386:#define __FLT_MIN__ 1.17549435e-38F
+// I386:#define __FLT_RADIX__ 2
+// I386:#define __INT16_TYPE__ short
+// I386:#define __INT32_TYPE__ int
+// I386:#define __INT64_TYPE__ long long int
+// I386:#define __INT8_TYPE__ char
+// I386:#define __INTMAX_MAX__ 9223372036854775807LL
+// I386:#define __INTMAX_TYPE__ long long int
+// I386:#define __INTPTR_TYPE__ int
+// I386:#define __INT_MAX__ 2147483647
+// I386:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+// I386:#define __LDBL_DIG__ 18
+// I386:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+// I386:#define __LDBL_HAS_DENORM__ 1
+// I386:#define __LDBL_HAS_INFINITY__ 1
+// I386:#define __LDBL_HAS_QUIET_NAN__ 1
+// I386:#define __LDBL_MANT_DIG__ 64
+// I386:#define __LDBL_MAX_10_EXP__ 4932
+// I386:#define __LDBL_MAX_EXP__ 16384
+// I386:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+// I386:#define __LDBL_MIN_10_EXP__ (-4931)
+// I386:#define __LDBL_MIN_EXP__ (-16381)
+// I386:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+// I386:#define __LITTLE_ENDIAN__ 1
+// I386:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// I386:#define __LONG_MAX__ 2147483647L
+// I386:#define __NO_INLINE__ 1
+// I386:#define __NO_MATH_INLINES 1
+// I386:#define __POINTER_WIDTH__ 32
+// I386:#define __PTRDIFF_TYPE__ int
+// I386:#define __REGISTER_PREFIX__
+// I386:#define __SCHAR_MAX__ 127
+// I386:#define __SHRT_MAX__ 32767
+// I386:#define __SIZE_TYPE__ unsigned int
+// I386:#define __UINTMAX_TYPE__ long long unsigned int
+// I386:#define __USER_LABEL_PREFIX__ _
+// I386:#define __WCHAR_MAX__ 2147483647
+// I386:#define __WCHAR_TYPE__ int
+// I386:#define __WINT_TYPE__ int
+// I386:#define __i386 1
+// I386:#define __i386__ 1
+// I386:#define __nocona 1
+// I386:#define __nocona__ 1
+// I386:#define __tune_nocona__ 1
+// I386:#define i386 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -check-prefix MSP430 %s &&
+//
+// MSP430:#define MSP430 1
+// MSP430:#define __CHAR_BIT__ 8
+// MSP430:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// MSP430:#define __DBL_DIG__ 15
+// MSP430:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// MSP430:#define __DBL_HAS_DENORM__ 1
+// MSP430:#define __DBL_HAS_INFINITY__ 1
+// MSP430:#define __DBL_HAS_QUIET_NAN__ 1
+// MSP430:#define __DBL_MANT_DIG__ 53
+// MSP430:#define __DBL_MAX_10_EXP__ 308
+// MSP430:#define __DBL_MAX_EXP__ 1024
+// MSP430:#define __DBL_MAX__ 1.7976931348623157e+308
+// MSP430:#define __DBL_MIN_10_EXP__ (-307)
+// MSP430:#define __DBL_MIN_EXP__ (-1021)
+// MSP430:#define __DBL_MIN__ 2.2250738585072014e-308
+// MSP430:#define __DECIMAL_DIG__ 17
+// MSP430:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// MSP430:#define __FLT_DIG__ 6
+// MSP430:#define __FLT_EPSILON__ 1.19209290e-7F
+// MSP430:#define __FLT_EVAL_METHOD__ 0
+// MSP430:#define __FLT_HAS_DENORM__ 1
+// MSP430:#define __FLT_HAS_INFINITY__ 1
+// MSP430:#define __FLT_HAS_QUIET_NAN__ 1
+// MSP430:#define __FLT_MANT_DIG__ 24
+// MSP430:#define __FLT_MAX_10_EXP__ 38
+// MSP430:#define __FLT_MAX_EXP__ 128
+// MSP430:#define __FLT_MAX__ 3.40282347e+38F
+// MSP430:#define __FLT_MIN_10_EXP__ (-37)
+// MSP430:#define __FLT_MIN_EXP__ (-125)
+// MSP430:#define __FLT_MIN__ 1.17549435e-38F
+// MSP430:#define __FLT_RADIX__ 2
+// MSP430:#define __INT16_TYPE__ short
+// MSP430:#define __INT32_TYPE__ long long
+// MSP430:#define __INT8_TYPE__ char
+// MSP430:#define __INTMAX_MAX__ 2147483647L
+// MSP430:#define __INTMAX_TYPE__ long int
+// MSP430:#define __INTPTR_TYPE__ short
+// MSP430:#define __INT_MAX__ 32767
+// MSP430:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// MSP430:#define __LDBL_DIG__ 15
+// MSP430:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// MSP430:#define __LDBL_HAS_DENORM__ 1
+// MSP430:#define __LDBL_HAS_INFINITY__ 1
+// MSP430:#define __LDBL_HAS_QUIET_NAN__ 1
+// MSP430:#define __LDBL_MANT_DIG__ 53
+// MSP430:#define __LDBL_MAX_10_EXP__ 308
+// MSP430:#define __LDBL_MAX_EXP__ 1024
+// MSP430:#define __LDBL_MAX__ 1.7976931348623157e+308
+// MSP430:#define __LDBL_MIN_10_EXP__ (-307)
+// MSP430:#define __LDBL_MIN_EXP__ (-1021)
+// MSP430:#define __LDBL_MIN__ 2.2250738585072014e-308
+// MSP430:#define __LONG_LONG_MAX__ 2147483647LL
+// MSP430:#define __LONG_MAX__ 2147483647L
+// MSP430:#define __MSP430__ 1
+// MSP430:#define __NO_INLINE__ 1
+// MSP430:#define __POINTER_WIDTH__ 16
+// MSP430:#define __PTRDIFF_TYPE__ int
+// MSP430:#define __SCHAR_MAX__ 127
+// MSP430:#define __SHRT_MAX__ 32767
+// MSP430:#define __SIZE_TYPE__ unsigned int
+// MSP430:#define __UINTMAX_TYPE__ long unsigned int
+// MSP430:#define __USER_LABEL_PREFIX__ _
+// MSP430:#define __WCHAR_MAX__ 2147483647
+// MSP430:#define __WCHAR_TYPE__ int
+// MSP430:#define __WINT_TYPE__ int
+// MSP430:#define __clang__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=pic16-none-none < /dev/null | FileCheck -check-prefix PIC16 %s &&
+//
+// PIC16:#define _CONFIG(conf) asm("CONFIG "#conf)
+// PIC16:#define __CHAR_BIT__ 8
+// PIC16:#define __DBL_DENORM_MIN__ 1.40129846e-45F
+// PIC16:#define __DBL_DIG__ 6
+// PIC16:#define __DBL_EPSILON__ 1.19209290e-7F
+// PIC16:#define __DBL_HAS_DENORM__ 1
+// PIC16:#define __DBL_HAS_INFINITY__ 1
+// PIC16:#define __DBL_HAS_QUIET_NAN__ 1
+// PIC16:#define __DBL_MANT_DIG__ 24
+// PIC16:#define __DBL_MAX_10_EXP__ 38
+// PIC16:#define __DBL_MAX_EXP__ 128
+// PIC16:#define __DBL_MAX__ 3.40282347e+38F
+// PIC16:#define __DBL_MIN_10_EXP__ (-37)
+// PIC16:#define __DBL_MIN_EXP__ (-125)
+// PIC16:#define __DBL_MIN__ 1.17549435e-38F
+// PIC16:#define __DECIMAL_DIG__ -1
+// PIC16:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// PIC16:#define __FLT_DIG__ 6
+// PIC16:#define __FLT_EPSILON__ 1.19209290e-7F
+// PIC16:#define __FLT_EVAL_METHOD__ 0
+// PIC16:#define __FLT_HAS_DENORM__ 1
+// PIC16:#define __FLT_HAS_INFINITY__ 1
+// PIC16:#define __FLT_HAS_QUIET_NAN__ 1
+// PIC16:#define __FLT_MANT_DIG__ 24
+// PIC16:#define __FLT_MAX_10_EXP__ 38
+// PIC16:#define __FLT_MAX_EXP__ 128
+// PIC16:#define __FLT_MAX__ 3.40282347e+38F
+// PIC16:#define __FLT_MIN_10_EXP__ (-37)
+// PIC16:#define __FLT_MIN_EXP__ (-125)
+// PIC16:#define __FLT_MIN__ 1.17549435e-38F
+// PIC16:#define __FLT_RADIX__ 2
+// PIC16:#define __INT16_TYPE__ short
+// PIC16:#define __INT32_TYPE__ long long
+// PIC16:#define __INT8_TYPE__ char
+// PIC16:#define __INTMAX_MAX__ 2147483647L
+// PIC16:#define __INTMAX_TYPE__ long int
+// PIC16:#define __INTPTR_TYPE__ short
+// PIC16:#define __INT_MAX__ 32767
+// PIC16:#define __LDBL_DENORM_MIN__ 1.40129846e-45F
+// PIC16:#define __LDBL_DIG__ 6
+// PIC16:#define __LDBL_EPSILON__ 1.19209290e-7F
+// PIC16:#define __LDBL_HAS_DENORM__ 1
+// PIC16:#define __LDBL_HAS_INFINITY__ 1
+// PIC16:#define __LDBL_HAS_QUIET_NAN__ 1
+// PIC16:#define __LDBL_MANT_DIG__ 24
+// PIC16:#define __LDBL_MAX_10_EXP__ 38
+// PIC16:#define __LDBL_MAX_EXP__ 128
+// PIC16:#define __LDBL_MAX__ 3.40282347e+38F
+// PIC16:#define __LDBL_MIN_10_EXP__ (-37)
+// PIC16:#define __LDBL_MIN_EXP__ (-125)
+// PIC16:#define __LDBL_MIN__ 1.17549435e-38F
+// PIC16:#define __LONG_LONG_MAX__ 2147483647LL
+// PIC16:#define __LONG_MAX__ 2147483647L
+// PIC16:#define __NO_INLINE__ 1
+// PIC16:#define __POINTER_WIDTH__ 16
+// PIC16:#define __PTRDIFF_TYPE__ int
+// PIC16:#define __SCHAR_MAX__ 127
+// PIC16:#define __SHRT_MAX__ 32767
+// PIC16:#define __SIZE_TYPE__ unsigned int
+// PIC16:#define __UINTMAX_TYPE__ long unsigned int
+// PIC16:#define __USER_LABEL_PREFIX__ _
+// PIC16:#define __WCHAR_MAX__ 2147483647
+// PIC16:#define __WCHAR_TYPE__ int
+// PIC16:#define __WINT_TYPE__ int
+// PIC16:#define __clang__ 1
+// PIC16:#define __llvm__ 1
+// PIC16:#define __pic16 1
+// PIC16:#define _address(Addr) __attribute__((section("Address="#Addr)))
+// PIC16:#define _interrupt __attribute__((section("interrupt=0x4"))) __attribute__((used))
+// PIC16:#define _section(SectName) __attribute__((section(SectName)))
+// PIC16:#define ram __attribute__((address_space(0)))
+// PIC16:#define rom __attribute__((address_space(1)))
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc64-none-none < /dev/null | FileCheck -check-prefix PPC64 %s &&
+//
+// PPC64:#define _ARCH_PPC 1
+// PPC64:#define _ARCH_PPC64 1
+// PPC64:#define _BIG_ENDIAN 1
+// PPC64:#define _LP64 1
+// PPC64:#define __BIG_ENDIAN__ 1
+// PPC64:#define __CHAR_BIT__ 8
+// PPC64:#define __CHAR_UNSIGNED__ 1
+// PPC64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// PPC64:#define __DBL_DIG__ 15
+// PPC64:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// PPC64:#define __DBL_HAS_DENORM__ 1
+// PPC64:#define __DBL_HAS_INFINITY__ 1
+// PPC64:#define __DBL_HAS_QUIET_NAN__ 1
+// PPC64:#define __DBL_MANT_DIG__ 53
+// PPC64:#define __DBL_MAX_10_EXP__ 308
+// PPC64:#define __DBL_MAX_EXP__ 1024
+// PPC64:#define __DBL_MAX__ 1.7976931348623157e+308
+// PPC64:#define __DBL_MIN_10_EXP__ (-307)
+// PPC64:#define __DBL_MIN_EXP__ (-1021)
+// PPC64:#define __DBL_MIN__ 2.2250738585072014e-308
+// PPC64:#define __DECIMAL_DIG__ 17
+// PPC64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// PPC64:#define __FLT_DIG__ 6
+// PPC64:#define __FLT_EPSILON__ 1.19209290e-7F
+// PPC64:#define __FLT_EVAL_METHOD__ 0
+// PPC64:#define __FLT_HAS_DENORM__ 1
+// PPC64:#define __FLT_HAS_INFINITY__ 1
+// PPC64:#define __FLT_HAS_QUIET_NAN__ 1
+// PPC64:#define __FLT_MANT_DIG__ 24
+// PPC64:#define __FLT_MAX_10_EXP__ 38
+// PPC64:#define __FLT_MAX_EXP__ 128
+// PPC64:#define __FLT_MAX__ 3.40282347e+38F
+// PPC64:#define __FLT_MIN_10_EXP__ (-37)
+// PPC64:#define __FLT_MIN_EXP__ (-125)
+// PPC64:#define __FLT_MIN__ 1.17549435e-38F
+// PPC64:#define __FLT_RADIX__ 2
+// PPC64:#define __INT16_TYPE__ short
+// PPC64:#define __INT32_TYPE__ int
+// PPC64:#define __INT64_TYPE__ long int
+// PPC64:#define __INT8_TYPE__ char
+// PPC64:#define __INTMAX_MAX__ 9223372036854775807L
+// PPC64:#define __INTMAX_TYPE__ long int
+// PPC64:#define __INTPTR_TYPE__ long int
+// PPC64:#define __INT_MAX__ 2147483647
+// PPC64:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// PPC64:#define __LDBL_DIG__ 15
+// PPC64:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// PPC64:#define __LDBL_HAS_DENORM__ 1
+// PPC64:#define __LDBL_HAS_INFINITY__ 1
+// PPC64:#define __LDBL_HAS_QUIET_NAN__ 1
+// PPC64:#define __LDBL_MANT_DIG__ 53
+// PPC64:#define __LDBL_MAX_10_EXP__ 308
+// PPC64:#define __LDBL_MAX_EXP__ 1024
+// PPC64:#define __LDBL_MAX__ 1.7976931348623157e+308
+// PPC64:#define __LDBL_MIN_10_EXP__ (-307)
+// PPC64:#define __LDBL_MIN_EXP__ (-1021)
+// PPC64:#define __LDBL_MIN__ 2.2250738585072014e-308
+// PPC64:#define __LONG_DOUBLE_128__ 1
+// PPC64:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// PPC64:#define __LONG_MAX__ 9223372036854775807L
+// PPC64:#define __LP64__ 1
+// PPC64:#define __NATURAL_ALIGNMENT__ 1
+// PPC64:#define __NO_INLINE__ 1
+// PPC64:#define __POINTER_WIDTH__ 64
+// PPC64:#define __POWERPC__ 1
+// PPC64:#define __PTRDIFF_TYPE__ long int
+// PPC64:#define __REGISTER_PREFIX__
+// PPC64:#define __SCHAR_MAX__ 127
+// PPC64:#define __SHRT_MAX__ 32767
+// PPC64:#define __SIZE_TYPE__ long unsigned int
+// PPC64:#define __UINTMAX_TYPE__ long unsigned int
+// PPC64:#define __USER_LABEL_PREFIX__ _
+// PPC64:#define __WCHAR_MAX__ 2147483647
+// PPC64:#define __WCHAR_TYPE__ int
+// PPC64:#define __WINT_TYPE__ int
+// PPC64:#define __ppc64__ 1
+// PPC64:#define __ppc__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=powerpc-none-none < /dev/null | FileCheck -check-prefix PPC %s &&
+//
+// PPC:#define _ARCH_PPC 1
+// PPC:#define _BIG_ENDIAN 1
+// PPC:#define __BIG_ENDIAN__ 1
+// PPC:#define __CHAR_BIT__ 8
+// PPC:#define __CHAR_UNSIGNED__ 1
+// PPC:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// PPC:#define __DBL_DIG__ 15
+// PPC:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// PPC:#define __DBL_HAS_DENORM__ 1
+// PPC:#define __DBL_HAS_INFINITY__ 1
+// PPC:#define __DBL_HAS_QUIET_NAN__ 1
+// PPC:#define __DBL_MANT_DIG__ 53
+// PPC:#define __DBL_MAX_10_EXP__ 308
+// PPC:#define __DBL_MAX_EXP__ 1024
+// PPC:#define __DBL_MAX__ 1.7976931348623157e+308
+// PPC:#define __DBL_MIN_10_EXP__ (-307)
+// PPC:#define __DBL_MIN_EXP__ (-1021)
+// PPC:#define __DBL_MIN__ 2.2250738585072014e-308
+// PPC:#define __DECIMAL_DIG__ 17
+// PPC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// PPC:#define __FLT_DIG__ 6
+// PPC:#define __FLT_EPSILON__ 1.19209290e-7F
+// PPC:#define __FLT_EVAL_METHOD__ 0
+// PPC:#define __FLT_HAS_DENORM__ 1
+// PPC:#define __FLT_HAS_INFINITY__ 1
+// PPC:#define __FLT_HAS_QUIET_NAN__ 1
+// PPC:#define __FLT_MANT_DIG__ 24
+// PPC:#define __FLT_MAX_10_EXP__ 38
+// PPC:#define __FLT_MAX_EXP__ 128
+// PPC:#define __FLT_MAX__ 3.40282347e+38F
+// PPC:#define __FLT_MIN_10_EXP__ (-37)
+// PPC:#define __FLT_MIN_EXP__ (-125)
+// PPC:#define __FLT_MIN__ 1.17549435e-38F
+// PPC:#define __FLT_RADIX__ 2
+// PPC:#define __INT16_TYPE__ short
+// PPC:#define __INT32_TYPE__ int
+// PPC:#define __INT64_TYPE__ long long int
+// PPC:#define __INT8_TYPE__ char
+// PPC:#define __INTMAX_MAX__ 9223372036854775807LL
+// PPC:#define __INTMAX_TYPE__ long long int
+// PPC:#define __INTPTR_TYPE__ long int
+// PPC:#define __INT_MAX__ 2147483647
+// PPC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// PPC:#define __LDBL_DIG__ 15
+// PPC:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// PPC:#define __LDBL_HAS_DENORM__ 1
+// PPC:#define __LDBL_HAS_INFINITY__ 1
+// PPC:#define __LDBL_HAS_QUIET_NAN__ 1
+// PPC:#define __LDBL_MANT_DIG__ 53
+// PPC:#define __LDBL_MAX_10_EXP__ 308
+// PPC:#define __LDBL_MAX_EXP__ 1024
+// PPC:#define __LDBL_MAX__ 1.7976931348623157e+308
+// PPC:#define __LDBL_MIN_10_EXP__ (-307)
+// PPC:#define __LDBL_MIN_EXP__ (-1021)
+// PPC:#define __LDBL_MIN__ 2.2250738585072014e-308
+// PPC:#define __LONG_DOUBLE_128__ 1
+// PPC:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// PPC:#define __LONG_MAX__ 2147483647L
+// PPC:#define __NATURAL_ALIGNMENT__ 1
+// PPC:#define __NO_INLINE__ 1
+// PPC:#define __POINTER_WIDTH__ 32
+// PPC:#define __POWERPC__ 1
+// PPC:#define __PTRDIFF_TYPE__ long int
+// PPC:#define __REGISTER_PREFIX__
+// PPC:#define __SCHAR_MAX__ 127
+// PPC:#define __SHRT_MAX__ 32767
+// PPC:#define __SIZE_TYPE__ long unsigned int
+// PPC:#define __UINTMAX_TYPE__ long long unsigned int
+// PPC:#define __USER_LABEL_PREFIX__ _
+// PPC:#define __WCHAR_MAX__ 2147483647
+// PPC:#define __WCHAR_TYPE__ int
+// PPC:#define __WINT_TYPE__ int
+// PPC:#define __ppc__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=s390x-none-none < /dev/null | FileCheck -check-prefix S390X %s &&
+//
+// S390X:#define __CHAR_BIT__ 8
+// S390X:#define __CHAR_UNSIGNED__ 1
+// S390X:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// S390X:#define __DBL_DIG__ 15
+// S390X:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// S390X:#define __DBL_HAS_DENORM__ 1
+// S390X:#define __DBL_HAS_INFINITY__ 1
+// S390X:#define __DBL_HAS_QUIET_NAN__ 1
+// S390X:#define __DBL_MANT_DIG__ 53
+// S390X:#define __DBL_MAX_10_EXP__ 308
+// S390X:#define __DBL_MAX_EXP__ 1024
+// S390X:#define __DBL_MAX__ 1.7976931348623157e+308
+// S390X:#define __DBL_MIN_10_EXP__ (-307)
+// S390X:#define __DBL_MIN_EXP__ (-1021)
+// S390X:#define __DBL_MIN__ 2.2250738585072014e-308
+// S390X:#define __DECIMAL_DIG__ 17
+// S390X:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// S390X:#define __FLT_DIG__ 6
+// S390X:#define __FLT_EPSILON__ 1.19209290e-7F
+// S390X:#define __FLT_EVAL_METHOD__ 0
+// S390X:#define __FLT_HAS_DENORM__ 1
+// S390X:#define __FLT_HAS_INFINITY__ 1
+// S390X:#define __FLT_HAS_QUIET_NAN__ 1
+// S390X:#define __FLT_MANT_DIG__ 24
+// S390X:#define __FLT_MAX_10_EXP__ 38
+// S390X:#define __FLT_MAX_EXP__ 128
+// S390X:#define __FLT_MAX__ 3.40282347e+38F
+// S390X:#define __FLT_MIN_10_EXP__ (-37)
+// S390X:#define __FLT_MIN_EXP__ (-125)
+// S390X:#define __FLT_MIN__ 1.17549435e-38F
+// S390X:#define __FLT_RADIX__ 2
+// S390X:#define __INT16_TYPE__ short
+// S390X:#define __INT32_TYPE__ int
+// S390X:#define __INT64_TYPE__ long long int
+// S390X:#define __INT8_TYPE__ char
+// S390X:#define __INTMAX_MAX__ 9223372036854775807LL
+// S390X:#define __INTMAX_TYPE__ long long int
+// S390X:#define __INTPTR_TYPE__ long int
+// S390X:#define __INT_MAX__ 2147483647
+// S390X:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// S390X:#define __LDBL_DIG__ 15
+// S390X:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// S390X:#define __LDBL_HAS_DENORM__ 1
+// S390X:#define __LDBL_HAS_INFINITY__ 1
+// S390X:#define __LDBL_HAS_QUIET_NAN__ 1
+// S390X:#define __LDBL_MANT_DIG__ 53
+// S390X:#define __LDBL_MAX_10_EXP__ 308
+// S390X:#define __LDBL_MAX_EXP__ 1024
+// S390X:#define __LDBL_MAX__ 1.7976931348623157e+308
+// S390X:#define __LDBL_MIN_10_EXP__ (-307)
+// S390X:#define __LDBL_MIN_EXP__ (-1021)
+// S390X:#define __LDBL_MIN__ 2.2250738585072014e-308
+// S390X:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// S390X:#define __LONG_MAX__ 9223372036854775807L
+// S390X:#define __NO_INLINE__ 1
+// S390X:#define __POINTER_WIDTH__ 64
+// S390X:#define __PTRDIFF_TYPE__ long int
+// S390X:#define __SCHAR_MAX__ 127
+// S390X:#define __SHRT_MAX__ 32767
+// S390X:#define __SIZE_TYPE__ long unsigned int
+// S390X:#define __UINTMAX_TYPE__ long long unsigned int
+// S390X:#define __USER_LABEL_PREFIX__ _
+// S390X:#define __WCHAR_MAX__ 2147483647
+// S390X:#define __WCHAR_TYPE__ int
+// S390X:#define __WINT_TYPE__ int
+// S390X:#define __s390__ 1
+// S390X:#define __s390x__ 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -check-prefix SPARC %s &&
+//
+// SPARC:#define __CHAR_BIT__ 8
+// SPARC:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// SPARC:#define __DBL_DIG__ 15
+// SPARC:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// SPARC:#define __DBL_HAS_DENORM__ 1
+// SPARC:#define __DBL_HAS_INFINITY__ 1
+// SPARC:#define __DBL_HAS_QUIET_NAN__ 1
+// SPARC:#define __DBL_MANT_DIG__ 53
+// SPARC:#define __DBL_MAX_10_EXP__ 308
+// SPARC:#define __DBL_MAX_EXP__ 1024
+// SPARC:#define __DBL_MAX__ 1.7976931348623157e+308
+// SPARC:#define __DBL_MIN_10_EXP__ (-307)
+// SPARC:#define __DBL_MIN_EXP__ (-1021)
+// SPARC:#define __DBL_MIN__ 2.2250738585072014e-308
+// SPARC:#define __DECIMAL_DIG__ 17
+// SPARC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// SPARC:#define __FLT_DIG__ 6
+// SPARC:#define __FLT_EPSILON__ 1.19209290e-7F
+// SPARC:#define __FLT_EVAL_METHOD__ 0
+// SPARC:#define __FLT_HAS_DENORM__ 1
+// SPARC:#define __FLT_HAS_INFINITY__ 1
+// SPARC:#define __FLT_HAS_QUIET_NAN__ 1
+// SPARC:#define __FLT_MANT_DIG__ 24
+// SPARC:#define __FLT_MAX_10_EXP__ 38
+// SPARC:#define __FLT_MAX_EXP__ 128
+// SPARC:#define __FLT_MAX__ 3.40282347e+38F
+// SPARC:#define __FLT_MIN_10_EXP__ (-37)
+// SPARC:#define __FLT_MIN_EXP__ (-125)
+// SPARC:#define __FLT_MIN__ 1.17549435e-38F
+// SPARC:#define __FLT_RADIX__ 2
+// SPARC:#define __INT16_TYPE__ short
+// SPARC:#define __INT32_TYPE__ int
+// SPARC:#define __INT64_TYPE__ long long int
+// SPARC:#define __INT8_TYPE__ char
+// SPARC:#define __INTMAX_MAX__ 9223372036854775807LL
+// SPARC:#define __INTMAX_TYPE__ long long int
+// SPARC:#define __INTPTR_TYPE__ long int
+// SPARC:#define __INT_MAX__ 2147483647
+// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324
+// SPARC:#define __LDBL_DIG__ 15
+// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16
+// SPARC:#define __LDBL_HAS_DENORM__ 1
+// SPARC:#define __LDBL_HAS_INFINITY__ 1
+// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
+// SPARC:#define __LDBL_MANT_DIG__ 53
+// SPARC:#define __LDBL_MAX_10_EXP__ 308
+// SPARC:#define __LDBL_MAX_EXP__ 1024
+// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308
+// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
+// SPARC:#define __LDBL_MIN_EXP__ (-1021)
+// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308
+// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// SPARC:#define __LONG_MAX__ 2147483647L
+// SPARC:#define __NO_INLINE__ 1
+// SPARC:#define __POINTER_WIDTH__ 32
+// SPARC:#define __PTRDIFF_TYPE__ long int
+// SPARC:#define __REGISTER_PREFIX__
+// SPARC:#define __SCHAR_MAX__ 127
+// SPARC:#define __SHRT_MAX__ 32767
+// SPARC:#define __SIZE_TYPE__ long unsigned int
+// SPARC:#define __UINTMAX_TYPE__ long long unsigned int
+// SPARC:#define __USER_LABEL_PREFIX__ _
+// SPARC:#define __VERSION__ "4.2.1 Compatible Clang Compiler"
+// SPARC:#define __WCHAR_MAX__ 2147483647
+// SPARC:#define __WCHAR_TYPE__ int
+// SPARC:#define __WINT_TYPE__ int
+// SPARC:#define __sparc 1
+// SPARC:#define __sparc__ 1
+// SPARC:#define __sparcv8 1
+// SPARC:#define sparc 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -check-prefix TCE %s &&
+//
+// TCE:#define __CHAR_BIT__ 8
+// TCE:#define __DBL_DENORM_MIN__ 1.40129846e-45F
+// TCE:#define __DBL_DIG__ 6
+// TCE:#define __DBL_EPSILON__ 1.19209290e-7F
+// TCE:#define __DBL_HAS_DENORM__ 1
+// TCE:#define __DBL_HAS_INFINITY__ 1
+// TCE:#define __DBL_HAS_QUIET_NAN__ 1
+// TCE:#define __DBL_MANT_DIG__ 24
+// TCE:#define __DBL_MAX_10_EXP__ 38
+// TCE:#define __DBL_MAX_EXP__ 128
+// TCE:#define __DBL_MAX__ 3.40282347e+38F
+// TCE:#define __DBL_MIN_10_EXP__ (-37)
+// TCE:#define __DBL_MIN_EXP__ (-125)
+// TCE:#define __DBL_MIN__ 1.17549435e-38F
+// TCE:#define __DECIMAL_DIG__ -1
+// TCE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// TCE:#define __FLT_DIG__ 6
+// TCE:#define __FLT_EPSILON__ 1.19209290e-7F
+// TCE:#define __FLT_EVAL_METHOD__ 0
+// TCE:#define __FLT_HAS_DENORM__ 1
+// TCE:#define __FLT_HAS_INFINITY__ 1
+// TCE:#define __FLT_HAS_QUIET_NAN__ 1
+// TCE:#define __FLT_MANT_DIG__ 24
+// TCE:#define __FLT_MAX_10_EXP__ 38
+// TCE:#define __FLT_MAX_EXP__ 128
+// TCE:#define __FLT_MAX__ 3.40282347e+38F
+// TCE:#define __FLT_MIN_10_EXP__ (-37)
+// TCE:#define __FLT_MIN_EXP__ (-125)
+// TCE:#define __FLT_MIN__ 1.17549435e-38F
+// TCE:#define __FLT_RADIX__ 2
+// TCE:#define __INT16_TYPE__ short
+// TCE:#define __INT32_TYPE__ int
+// TCE:#define __INT8_TYPE__ char
+// TCE:#define __INTMAX_MAX__ 2147483647L
+// TCE:#define __INTMAX_TYPE__ long int
+// TCE:#define __INTPTR_TYPE__ int
+// TCE:#define __INT_MAX__ 2147483647
+// TCE:#define __LDBL_DENORM_MIN__ 1.40129846e-45F
+// TCE:#define __LDBL_DIG__ 6
+// TCE:#define __LDBL_EPSILON__ 1.19209290e-7F
+// TCE:#define __LDBL_HAS_DENORM__ 1
+// TCE:#define __LDBL_HAS_INFINITY__ 1
+// TCE:#define __LDBL_HAS_QUIET_NAN__ 1
+// TCE:#define __LDBL_MANT_DIG__ 24
+// TCE:#define __LDBL_MAX_10_EXP__ 38
+// TCE:#define __LDBL_MAX_EXP__ 128
+// TCE:#define __LDBL_MAX__ 3.40282347e+38F
+// TCE:#define __LDBL_MIN_10_EXP__ (-37)
+// TCE:#define __LDBL_MIN_EXP__ (-125)
+// TCE:#define __LDBL_MIN__ 1.17549435e-38F
+// TCE:#define __LONG_LONG_MAX__ 2147483647LL
+// TCE:#define __LONG_MAX__ 2147483647L
+// TCE:#define __NO_INLINE__ 1
+// TCE:#define __POINTER_WIDTH__ 32
+// TCE:#define __PTRDIFF_TYPE__ int
+// TCE:#define __SCHAR_MAX__ 127
+// TCE:#define __SHRT_MAX__ 32767
+// TCE:#define __SIZE_TYPE__ unsigned int
+// TCE:#define __TCE_V1__ 1
+// TCE:#define __TCE__ 1
+// TCE:#define __UINTMAX_TYPE__ long unsigned int
+// TCE:#define __USER_LABEL_PREFIX__ _
+// TCE:#define __WCHAR_MAX__ 2147483647
+// TCE:#define __WCHAR_TYPE__ int
+// TCE:#define __WINT_TYPE__ int
+// TCE:#define __tce 1
+// TCE:#define __tce__ 1
+// TCE:#define tce 1
+//
+// RUN: clang-cc -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -check-prefix X86_64 %s &&
+//
+// X86_64:#define _LP64 1
+// X86_64:#define __CHAR_BIT__ 8
+// X86_64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// X86_64:#define __DBL_DIG__ 15
+// X86_64:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// X86_64:#define __DBL_HAS_DENORM__ 1
+// X86_64:#define __DBL_HAS_INFINITY__ 1
+// X86_64:#define __DBL_HAS_QUIET_NAN__ 1
+// X86_64:#define __DBL_MANT_DIG__ 53
+// X86_64:#define __DBL_MAX_10_EXP__ 308
+// X86_64:#define __DBL_MAX_EXP__ 1024
+// X86_64:#define __DBL_MAX__ 1.7976931348623157e+308
+// X86_64:#define __DBL_MIN_10_EXP__ (-307)
+// X86_64:#define __DBL_MIN_EXP__ (-1021)
+// X86_64:#define __DBL_MIN__ 2.2250738585072014e-308
+// X86_64:#define __DECIMAL_DIG__ 21
+// X86_64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// X86_64:#define __FLT_DIG__ 6
+// X86_64:#define __FLT_EPSILON__ 1.19209290e-7F
+// X86_64:#define __FLT_EVAL_METHOD__ 0
+// X86_64:#define __FLT_HAS_DENORM__ 1
+// X86_64:#define __FLT_HAS_INFINITY__ 1
+// X86_64:#define __FLT_HAS_QUIET_NAN__ 1
+// X86_64:#define __FLT_MANT_DIG__ 24
+// X86_64:#define __FLT_MAX_10_EXP__ 38
+// X86_64:#define __FLT_MAX_EXP__ 128
+// X86_64:#define __FLT_MAX__ 3.40282347e+38F
+// X86_64:#define __FLT_MIN_10_EXP__ (-37)
+// X86_64:#define __FLT_MIN_EXP__ (-125)
+// X86_64:#define __FLT_MIN__ 1.17549435e-38F
+// X86_64:#define __FLT_RADIX__ 2
+// X86_64:#define __INT16_TYPE__ short
+// X86_64:#define __INT32_TYPE__ int
+// X86_64:#define __INT64_TYPE__ long int
+// X86_64:#define __INT8_TYPE__ char
+// X86_64:#define __INTMAX_MAX__ 9223372036854775807L
+// X86_64:#define __INTMAX_TYPE__ long int
+// X86_64:#define __INTPTR_TYPE__ long int
+// X86_64:#define __INT_MAX__ 2147483647
+// X86_64:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+// X86_64:#define __LDBL_DIG__ 18
+// X86_64:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+// X86_64:#define __LDBL_HAS_DENORM__ 1
+// X86_64:#define __LDBL_HAS_INFINITY__ 1
+// X86_64:#define __LDBL_HAS_QUIET_NAN__ 1
+// X86_64:#define __LDBL_MANT_DIG__ 64
+// X86_64:#define __LDBL_MAX_10_EXP__ 4932
+// X86_64:#define __LDBL_MAX_EXP__ 16384
+// X86_64:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+// X86_64:#define __LDBL_MIN_10_EXP__ (-4931)
+// X86_64:#define __LDBL_MIN_EXP__ (-16381)
+// X86_64:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+// X86_64:#define __LITTLE_ENDIAN__ 1
+// X86_64:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// X86_64:#define __LONG_MAX__ 9223372036854775807L
+// X86_64:#define __LP64__ 1
+// X86_64:#define __MMX__ 1
+// X86_64:#define __NO_INLINE__ 1
+// X86_64:#define __NO_MATH_INLINES 1
+// X86_64:#define __POINTER_WIDTH__ 64
+// X86_64:#define __PTRDIFF_TYPE__ long int
+// X86_64:#define __REGISTER_PREFIX__
+// X86_64:#define __SCHAR_MAX__ 127
+// X86_64:#define __SHRT_MAX__ 32767
+// X86_64:#define __SIZE_TYPE__ long unsigned int
+// X86_64:#define __SSE2_MATH__ 1
+// X86_64:#define __SSE2__ 1
+// X86_64:#define __SSE_MATH__ 1
+// X86_64:#define __SSE__ 1
+// X86_64:#define __UINTMAX_TYPE__ long unsigned int
+// X86_64:#define __USER_LABEL_PREFIX__ _
+// X86_64:#define __WCHAR_MAX__ 2147483647
+// X86_64:#define __WCHAR_TYPE__ int
+// X86_64:#define __WINT_TYPE__ int
+// X86_64:#define __amd64 1
+// X86_64:#define __amd64__ 1
+// X86_64:#define __nocona 1
+// X86_64:#define __nocona__ 1
+// X86_64:#define __tune_nocona__ 1
+// X86_64:#define __x86_64 1
+// X86_64:#define __x86_64__ 1
+//
+// RUN: true
diff --git a/test/Preprocessor/line-directive.c b/test/Preprocessor/line-directive.c
index ed9a6c40e5d7..4ebf95bab44c 100644
--- a/test/Preprocessor/line-directive.c
+++ b/test/Preprocessor/line-directive.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify -pedantic %s &&
+// RUN: clang-cc -fsyntax-only -verify -pedantic -fms-extensions=0 %s &&
// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:92:2: error: #error ABC' &&
// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:93:2: error: #error DEF'
diff --git a/test/Preprocessor/macro_disable3.c b/test/Preprocessor/macro_disable3.c
index 011de3beed3d..d4a5664ae999 100644
--- a/test/Preprocessor/macro_disable3.c
+++ b/test/Preprocessor/macro_disable3.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -E | grep -F 'f(2 * (f(2 * (z[0]))));'
+// RUN: clang-cc %s -E | FileCheck -strict-whitespace %s
// Check for C99 6.10.3.4p2.
#define f(a) f(x * (a))
@@ -6,3 +6,5 @@
#define z z[0]
f(f(z));
+// CHECK: f(2 * (f(2 * (z[0]))));
+
diff --git a/test/Preprocessor/macro_paste_mscomment.c b/test/Preprocessor/macro_paste_mscomment.c
index d6ead91068cf..ecd0b9d6a850 100644
--- a/test/Preprocessor/macro_paste_mscomment.c
+++ b/test/Preprocessor/macro_paste_mscomment.c
@@ -1,5 +1,4 @@
-// RUN: clang-cc -P -E -fms-extensions %s | sed '/^#.\+/d' | tr -d '\n' > %t &&
-// RUN: grep '^int foo;int bar;int baz;$' %t | count 1
+// RUN: clang-cc -P -E -fms-extensions %s | FileCheck -strict-whitespace %s
// This horrible stuff should preprocess into (other than whitespace):
// int foo;
// int bar;
@@ -7,14 +6,21 @@
int foo;
+// CHECK: int foo;
+
#define comment /##/ dead tokens live here
comment This is stupidity
int bar;
+// CHECK: int bar;
+
#define nested(x) int x comment cute little dead tokens...
nested(baz) rise of the dead tokens
;
+// CHECK: int baz
+// CHECK: ;
+
diff --git a/test/Preprocessor/macro_rescan_varargs.c b/test/Preprocessor/macro_rescan_varargs.c
index ed1056ab1b3f..8a3ad151141f 100644
--- a/test/Preprocessor/macro_rescan_varargs.c
+++ b/test/Preprocessor/macro_rescan_varargs.c
@@ -1,5 +1,5 @@
-// RUN: clang-cc -E %s | grep -F "1: F, (, 'a', 'b', );" &&
-// RUN: clang-cc -E %s | grep -F "2: 'a' + 'b';"
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
+
#define LPAREN (
#define RPAREN )
#define F(x, y) x + y
@@ -8,3 +8,6 @@
1: ELLIP_FUNC(F, LPAREN, 'a', 'b', RPAREN); /* 1st invocation */
2: ELLIP_FUNC(F LPAREN 'a', 'b' RPAREN); /* 2nd invocation */
+// CHECK: 1: F, (, 'a', 'b', );
+// CHECK: 2: 'a' + 'b';
+
diff --git a/test/Preprocessor/macro_rparen_scan2.c b/test/Preprocessor/macro_rparen_scan2.c
index 41748ac459b9..c7fb9e3b08c9 100644
--- a/test/Preprocessor/macro_rparen_scan2.c
+++ b/test/Preprocessor/macro_rparen_scan2.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc -E %s | grep -F 'static int glob = (1 + 1 );'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define R_PAREN )
@@ -6,3 +6,5 @@
static int glob = (1 + FUNC(1 R_PAREN );
+// CHECK: static int glob = (1 + 1 );
+
diff --git a/test/Preprocessor/macro_undef.c b/test/Preprocessor/macro_undef.c
new file mode 100644
index 000000000000..4507cddcb796
--- /dev/null
+++ b/test/Preprocessor/macro_undef.c
@@ -0,0 +1,4 @@
+// RUN: clang-cc -dM -undef -Dfoo=1 -E %s | FileCheck %s
+
+// CHECK-NOT: #define __clang__
+// CHECK: #define foo 1
diff --git a/test/Preprocessor/output_paste_avoid.c b/test/Preprocessor/output_paste_avoid.c
index ff8afc3e47ac..200ced9fba7a 100644
--- a/test/Preprocessor/output_paste_avoid.c
+++ b/test/Preprocessor/output_paste_avoid.c
@@ -1,23 +1,26 @@
-// RUN: clang-cc -E %s -o %t &&
-// This should print as ".. ." to avoid turning into ...
-// RUN: grep -F 'A: . . .' %t &&
+// RUN: clang-cc -E %s -o - | FileCheck -strict-whitespace %s
+
+
#define y(a) ..a
A: y(.)
+// This should print as ".. ." to avoid turning into ...
+// CHECK: A: . . .
+
-// RUN: grep -F 'C: .. .' %t &&
#define DOT .
C: ..DOT
+// CHECK: C: .. .
-// RUN: grep -F 'D: + + - - + + = = =' %t &&
#define PLUS +
#define EMPTY
#define f(x) =x=
D: +PLUS -EMPTY- PLUS+ f(=)
+// CHECK: D: + + - - + + = = =
-// RUN: grep -F 'E: L "str"' %t
-// Should expand to L "str" not L"str"
#define test(x) L#x
E: test(str)
+// Should expand to L "str" not L"str"
+// CHECK: E: L "str"
diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c
new file mode 100644
index 000000000000..e292bd3ec7e5
--- /dev/null
+++ b/test/Preprocessor/stdint.c
@@ -0,0 +1,1244 @@
+// RUN: clang-cc -E -ffreestanding -triple=arm-none-none %s | FileCheck -check-prefix ARM %s &&
+//
+// ARM:typedef signed char int8_t;
+// ARM:typedef short int16_t;
+// ARM:typedef int int32_t;
+// ARM:typedef long long int int64_t;
+//
+// ARM:typedef unsigned char uint8_t;
+// ARM:typedef int8_t int_least8_t;
+// ARM:typedef uint8_t uint_least8_t;
+// ARM:typedef int8_t int_fast8_t;
+// ARM:typedef uint8_t uint_fast8_t;
+//
+// ARM:typedef unsigned short uint16_t;
+// ARM:typedef int16_t int_least16_t;
+// ARM:typedef uint16_t uint_least16_t;
+// ARM:typedef int16_t int_fast16_t;
+// ARM:typedef uint16_t uint_fast16_t;
+//
+// ARM:typedef unsigned int uint32_t;
+// ARM:typedef int32_t int_least32_t;
+// ARM:typedef uint32_t uint_least32_t;
+// ARM:typedef int32_t int_fast32_t;
+// ARM:typedef uint32_t uint_fast32_t;
+//
+// ARM:typedef unsigned long long int uint64_t;
+// ARM:typedef int64_t int_least64_t;
+// ARM:typedef uint64_t uint_least64_t;
+// ARM:typedef int64_t int_fast64_t;
+// ARM:typedef uint64_t uint_fast64_t;
+//
+// ARM:typedef long int intptr_t;
+// ARM:typedef unsigned long int uintptr_t;
+//
+// ARM:typedef long long int intmax_t;
+// ARM:typedef long long unsigned int uintmax_t;
+//
+// ARM:INT8_MAX_ 127
+// ARM:INT8_MIN_ (-128)
+// ARM:UINT8_MAX_ 255
+// ARM:INT_LEAST8_MIN_ (-128)
+// ARM:INT_LEAST8_MAX_ 127
+// ARM:UINT_LEAST8_MAX_ 255
+// ARM:INT_FAST8_MIN_ (-128)
+// ARM:INT_FAST8_MAX_ 127
+// ARM:UINT_FAST8_MAX_ 255
+//
+// ARM:INT16_MAX_ 32767
+// ARM:INT16_MIN_ (-32768)
+// ARM:UINT16_MAX_ 65535
+// ARM:INT_LEAST16_MIN_ (-32768)
+// ARM:INT_LEAST16_MAX_ 32767
+// ARM:UINT_LEAST16_MAX_ 65535
+// ARM:INT_FAST16_MIN_ (-32768)
+// ARM:INT_FAST16_MAX_ 32767
+// ARM:UINT_FAST16_MAX_ 65535
+//
+// ARM:INT32_MAX_ 2147483647
+// ARM:INT32_MIN_ (-2147483647 -1)
+// ARM:UINT32_MAX_ 4294967295U
+// ARM:INT_LEAST32_MIN_ (-2147483647 -1)
+// ARM:INT_LEAST32_MAX_ 2147483647
+// ARM:UINT_LEAST32_MAX_ 4294967295U
+// ARM:INT_FAST32_MIN_ (-2147483647 -1)
+// ARM:INT_FAST32_MAX_ 2147483647
+// ARM:UINT_FAST32_MAX_ 4294967295U
+//
+// ARM:INT64_MAX_ 9223372036854775807LL
+// ARM:INT64_MIN_ (-9223372036854775807LL -1)
+// ARM:UINT64_MAX_ 18446744073709551615ULL
+// ARM:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// ARM:INT_LEAST64_MAX_ 9223372036854775807LL
+// ARM:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// ARM:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// ARM:INT_FAST64_MAX_ 9223372036854775807LL
+// ARM:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// ARM:INTPTR_MIN_ (-2147483647 -1)
+// ARM:INTPTR_MAX_ 2147483647
+// ARM:UINTPTR_MAX_ 4294967295U
+// ARM:PTRDIFF_MIN_ (-2147483647 -1)
+// ARM:PTRDIFF_MAX_ 2147483647
+// ARM:SIZE_MAX_ 4294967295U
+//
+// ARM:INTMAX_MIN_ (-9223372036854775807LL -1)
+// ARM:INTMAX_MAX_ 9223372036854775807LL
+// ARM:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// ARM:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// ARM:SIG_ATOMIC_MAX_ 2147483647
+// ARM:WINT_MIN_ (-2147483647 -1)
+// ARM:WINT_MAX_ 2147483647
+//
+// ARM:WCHAR_MAX_ 2147483647
+// ARM:WCHAR_MIN_ (-2147483647 -1)
+//
+// ARM:INT8_C_(0) (0)
+// ARM:UINT8_C_(0) (0U)
+// ARM:INT16_C_(0) (0)
+// ARM:UINT16_C_(0) (0U)
+// ARM:INT32_C_(0) (0)
+// ARM:UINT32_C_(0) (0U)
+// ARM:INT64_C_(0) (0LL)
+// ARM:UINT64_C_(0) (0ULL)
+//
+// ARM:INTMAX_C_(0) (0LL)
+// ARM:UINTMAX_C_(0) (0ULL)
+//
+//
+// RUN: clang-cc -E -ffreestanding -triple=bfin-none-none %s | FileCheck -check-prefix BFIN %s &&
+//
+// BFIN:typedef signed char int8_t;
+// BFIN:typedef short int16_t;
+// BFIN:typedef int int32_t;
+//
+// BFIN:typedef long long int int64_t;
+//
+// BFIN:typedef unsigned char uint8_t;
+// BFIN:typedef int8_t int_least8_t;
+// BFIN:typedef uint8_t uint_least8_t;
+// BFIN:typedef int8_t int_fast8_t;
+// BFIN:typedef uint8_t uint_fast8_t;
+//
+// BFIN:typedef unsigned short uint16_t;
+// BFIN:typedef int16_t int_least16_t;
+// BFIN:typedef uint16_t uint_least16_t;
+// BFIN:typedef int16_t int_fast16_t;
+// BFIN:typedef uint16_t uint_fast16_t;
+//
+// BFIN:typedef unsigned int uint32_t;
+// BFIN:typedef int32_t int_least32_t;
+// BFIN:typedef uint32_t uint_least32_t;
+// BFIN:typedef int32_t int_fast32_t;
+// BFIN:typedef uint32_t uint_fast32_t;
+//
+// BFIN:typedef unsigned long long int uint64_t;
+// BFIN:typedef int64_t int_least64_t;
+// BFIN:typedef uint64_t uint_least64_t;
+// BFIN:typedef int64_t int_fast64_t;
+// BFIN:typedef uint64_t uint_fast64_t;
+//
+// BFIN:typedef long int intptr_t;
+// BFIN:typedef unsigned long int uintptr_t;
+//
+// BFIN:typedef long long int intmax_t;
+// BFIN:typedef long long unsigned int uintmax_t;
+//
+// BFIN:INT8_MAX_ 127
+// BFIN:INT8_MIN_ (-128)
+// BFIN:UINT8_MAX_ 255
+// BFIN:INT_LEAST8_MIN_ (-128)
+// BFIN:INT_LEAST8_MAX_ 127
+// BFIN:UINT_LEAST8_MAX_ 255
+// BFIN:INT_FAST8_MIN_ (-128)
+// BFIN:INT_FAST8_MAX_ 127
+// BFIN:UINT_FAST8_MAX_ 255
+//
+// BFIN:INT16_MAX_ 32767
+// BFIN:INT16_MIN_ (-32768)
+// BFIN:UINT16_MAX_ 65535
+// BFIN:INT_LEAST16_MIN_ (-32768)
+// BFIN:INT_LEAST16_MAX_ 32767
+// BFIN:UINT_LEAST16_MAX_ 65535
+// BFIN:INT_FAST16_MIN_ (-32768)
+// BFIN:INT_FAST16_MAX_ 32767
+// BFIN:UINT_FAST16_MAX_ 65535
+//
+// BFIN:INT32_MAX_ 2147483647
+// BFIN:INT32_MIN_ (-2147483647 -1)
+// BFIN:UINT32_MAX_ 4294967295U
+// BFIN:INT_LEAST32_MIN_ (-2147483647 -1)
+// BFIN:INT_LEAST32_MAX_ 2147483647
+// BFIN:UINT_LEAST32_MAX_ 4294967295U
+// BFIN:INT_FAST32_MIN_ (-2147483647 -1)
+// BFIN:INT_FAST32_MAX_ 2147483647
+// BFIN:UINT_FAST32_MAX_ 4294967295U
+//
+// BFIN:INT64_MAX_ 9223372036854775807LL
+// BFIN:INT64_MIN_ (-9223372036854775807LL -1)
+// BFIN:UINT64_MAX_ 18446744073709551615ULL
+// BFIN:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// BFIN:INT_LEAST64_MAX_ 9223372036854775807LL
+// BFIN:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// BFIN:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// BFIN:INT_FAST64_MAX_ 9223372036854775807LL
+// BFIN:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// BFIN:INTPTR_MIN_ (-2147483647 -1)
+// BFIN:INTPTR_MAX_ 2147483647
+// BFIN:UINTPTR_MAX_ 4294967295U
+// BFIN:PTRDIFF_MIN_ (-2147483647 -1)
+// BFIN:PTRDIFF_MAX_ 2147483647
+// BFIN:SIZE_MAX_ 4294967295U
+//
+// BFIN:INTMAX_MIN_ (-9223372036854775807LL -1)
+// BFIN:INTMAX_MAX_ 9223372036854775807LL
+// BFIN:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// BFIN:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// BFIN:SIG_ATOMIC_MAX_ 2147483647
+// BFIN:WINT_MIN_ (-2147483647 -1)
+// BFIN:WINT_MAX_ 2147483647
+//
+// BFIN:WCHAR_MAX_ 2147483647
+// BFIN:WCHAR_MIN_ (-2147483647 -1)
+//
+// BFIN:INT8_C_(0) (0)
+// BFIN:UINT8_C_(0) (0U)
+// BFIN:INT16_C_(0) (0)
+// BFIN:UINT16_C_(0) (0U)
+// BFIN:INT32_C_(0) (0)
+// BFIN:UINT32_C_(0) (0U)
+// BFIN:INT64_C_(0) (0LL)
+// BFIN:UINT64_C_(0) (0ULL)
+//
+// BFIN:INTMAX_C_(0) (0LL)
+// BFIN:UINTMAX_C_(0) (0ULL)
+//
+//
+// RUN: clang-cc -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s &&
+//
+// I386:typedef signed char int8_t;
+// I386:typedef short int16_t;
+// I386:typedef int int32_t;
+// I386:typedef long long int int64_t;
+//
+// I386:typedef unsigned char uint8_t;
+// I386:typedef int8_t int_least8_t;
+// I386:typedef uint8_t uint_least8_t;
+// I386:typedef int8_t int_fast8_t;
+// I386:typedef uint8_t uint_fast8_t;
+//
+// I386:typedef unsigned short uint16_t;
+// I386:typedef int16_t int_least16_t;
+// I386:typedef uint16_t uint_least16_t;
+// I386:typedef int16_t int_fast16_t;
+// I386:typedef uint16_t uint_fast16_t;
+//
+// I386:typedef unsigned int uint32_t;
+// I386:typedef int32_t int_least32_t;
+// I386:typedef uint32_t uint_least32_t;
+// I386:typedef int32_t int_fast32_t;
+// I386:typedef uint32_t uint_fast32_t;
+//
+// I386:typedef unsigned long long int uint64_t;
+// I386:typedef int64_t int_least64_t;
+// I386:typedef uint64_t uint_least64_t;
+// I386:typedef int64_t int_fast64_t;
+// I386:typedef uint64_t uint_fast64_t;
+//
+// I386:typedef int intptr_t;
+// I386:typedef unsigned int uintptr_t;
+//
+// I386:typedef long long int intmax_t;
+// I386:typedef long long unsigned int uintmax_t;
+//
+// I386:INT8_MAX_ 127
+// I386:INT8_MIN_ (-128)
+// I386:UINT8_MAX_ 255
+// I386:INT_LEAST8_MIN_ (-128)
+// I386:INT_LEAST8_MAX_ 127
+// I386:UINT_LEAST8_MAX_ 255
+// I386:INT_FAST8_MIN_ (-128)
+// I386:INT_FAST8_MAX_ 127
+// I386:UINT_FAST8_MAX_ 255
+//
+// I386:INT16_MAX_ 32767
+// I386:INT16_MIN_ (-32768)
+// I386:UINT16_MAX_ 65535
+// I386:INT_LEAST16_MIN_ (-32768)
+// I386:INT_LEAST16_MAX_ 32767
+// I386:UINT_LEAST16_MAX_ 65535
+// I386:INT_FAST16_MIN_ (-32768)
+// I386:INT_FAST16_MAX_ 32767
+// I386:UINT_FAST16_MAX_ 65535
+//
+// I386:INT32_MAX_ 2147483647
+// I386:INT32_MIN_ (-2147483647 -1)
+// I386:UINT32_MAX_ 4294967295U
+// I386:INT_LEAST32_MIN_ (-2147483647 -1)
+// I386:INT_LEAST32_MAX_ 2147483647
+// I386:UINT_LEAST32_MAX_ 4294967295U
+// I386:INT_FAST32_MIN_ (-2147483647 -1)
+// I386:INT_FAST32_MAX_ 2147483647
+// I386:UINT_FAST32_MAX_ 4294967295U
+//
+// I386:INT64_MAX_ 9223372036854775807LL
+// I386:INT64_MIN_ (-9223372036854775807LL -1)
+// I386:UINT64_MAX_ 18446744073709551615ULL
+// I386:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// I386:INT_LEAST64_MAX_ 9223372036854775807LL
+// I386:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// I386:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// I386:INT_FAST64_MAX_ 9223372036854775807LL
+// I386:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// I386:INTPTR_MIN_ (-2147483647 -1)
+// I386:INTPTR_MAX_ 2147483647
+// I386:UINTPTR_MAX_ 4294967295U
+// I386:PTRDIFF_MIN_ (-2147483647 -1)
+// I386:PTRDIFF_MAX_ 2147483647
+// I386:SIZE_MAX_ 4294967295U
+//
+// I386:INTMAX_MIN_ (-9223372036854775807LL -1)
+// I386:INTMAX_MAX_ 9223372036854775807LL
+// I386:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// I386:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// I386:SIG_ATOMIC_MAX_ 2147483647
+// I386:WINT_MIN_ (-2147483647 -1)
+// I386:WINT_MAX_ 2147483647
+//
+// I386:WCHAR_MAX_ 2147483647
+// I386:WCHAR_MIN_ (-2147483647 -1)
+//
+// I386:INT8_C_(0) (0)
+// I386:UINT8_C_(0) (0U)
+// I386:INT16_C_(0) (0)
+// I386:UINT16_C_(0) (0U)
+// I386:INT32_C_(0) (0)
+// I386:UINT32_C_(0) (0U)
+// I386:INT64_C_(0) (0LL)
+// I386:UINT64_C_(0) (0ULL)
+//
+// I386:INTMAX_C_(0) (0LL)
+// I386:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=msp430-none-none %s | FileCheck -check-prefix MSP430 %s &&
+//
+// MSP430:typedef signed char int8_t;
+// MSP430:typedef short int16_t;
+// MSP430:typedef long long int32_t;
+//
+// MSP430:typedef unsigned char uint8_t;
+// MSP430:typedef int8_t int_least8_t;
+// MSP430:typedef uint8_t uint_least8_t;
+// MSP430:typedef int8_t int_fast8_t;
+// MSP430:typedef uint8_t uint_fast8_t;
+//
+// MSP430:typedef unsigned short uint16_t;
+// MSP430:typedef int16_t int_least16_t;
+// MSP430:typedef uint16_t uint_least16_t;
+// MSP430:typedef int16_t int_fast16_t;
+// MSP430:typedef uint16_t uint_fast16_t;
+//
+// MSP430:typedef unsigned long long uint32_t;
+// MSP430:typedef int32_t int_least32_t;
+// MSP430:typedef uint32_t uint_least32_t;
+// MSP430:typedef int32_t int_fast32_t;
+// MSP430:typedef uint32_t uint_fast32_t;
+//
+// MSP430:typedef short intptr_t;
+// MSP430:typedef unsigned short uintptr_t;
+//
+// MSP430:typedef long int intmax_t;
+// MSP430:typedef long unsigned int uintmax_t;
+//
+// MSP430:INT8_MAX_ 127
+// MSP430:INT8_MIN_ (-128)
+// MSP430:UINT8_MAX_ 255
+// MSP430:INT_LEAST8_MIN_ (-128)
+// MSP430:INT_LEAST8_MAX_ 127
+// MSP430:UINT_LEAST8_MAX_ 255
+// MSP430:INT_FAST8_MIN_ (-128)
+// MSP430:INT_FAST8_MAX_ 127
+// MSP430:UINT_FAST8_MAX_ 255
+//
+// MSP430:INT16_MAX_ 32767
+// MSP430:INT16_MIN_ (-32768)
+// MSP430:UINT16_MAX_ 65535
+// MSP430:INT_LEAST16_MIN_ (-32768)
+// MSP430:INT_LEAST16_MAX_ 32767
+// MSP430:UINT_LEAST16_MAX_ 65535
+// MSP430:INT_FAST16_MIN_ (-32768)
+// MSP430:INT_FAST16_MAX_ 32767
+// MSP430:UINT_FAST16_MAX_ 65535
+//
+// MSP430:INT32_MAX_ 2147483647
+// MSP430:INT32_MIN_ (-2147483647 -1)
+// MSP430:UINT32_MAX_ 4294967295U
+// MSP430:INT_LEAST32_MIN_ (-2147483647 -1)
+// MSP430:INT_LEAST32_MAX_ 2147483647
+// MSP430:UINT_LEAST32_MAX_ 4294967295U
+// MSP430:INT_FAST32_MIN_ (-2147483647 -1)
+// MSP430:INT_FAST32_MAX_ 2147483647
+// MSP430:UINT_FAST32_MAX_ 4294967295U
+//
+// MSP430:INT64_MAX_ INT64_MAX
+// MSP430:INT64_MIN_ INT64_MIN
+// MSP430:UINT64_MAX_ UINT64_MAX
+// MSP430:INT_LEAST64_MIN_ INT_LEAST64_MIN
+// MSP430:INT_LEAST64_MAX_ INT_LEAST64_MAX
+// MSP430:UINT_LEAST64_MAX_ UINT_LEAST64_MAX
+// MSP430:INT_FAST64_MIN_ INT_FAST64_MIN
+// MSP430:INT_FAST64_MAX_ INT_FAST64_MAX
+// MSP430:UINT_FAST64_MAX_ UINT_FAST64_MAX
+//
+// MSP430:INTPTR_MIN_ (-32768)
+// MSP430:INTPTR_MAX_ 32767
+// MSP430:UINTPTR_MAX_ 65535
+// MSP430:PTRDIFF_MIN_ (-32768)
+// MSP430:PTRDIFF_MAX_ 32767
+// MSP430:SIZE_MAX_ 65535
+//
+// MSP430:INTMAX_MIN_ (-2147483647L -1)
+// MSP430:INTMAX_MAX_ 2147483647L
+// MSP430:UINTMAX_MAX_ (2147483647L*2ULL +1ULL)
+//
+// MSP430:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// MSP430:SIG_ATOMIC_MAX_ 2147483647
+// MSP430:WINT_MIN_ (-2147483647 -1)
+// MSP430:WINT_MAX_ 2147483647
+//
+// MSP430:WCHAR_MAX_ 2147483647
+// MSP430:WCHAR_MIN_ (-2147483647 -1)
+//
+// MSP430:INT8_C_(0) (0)
+// MSP430:UINT8_C_(0) (0U)
+// MSP430:INT16_C_(0) (0)
+// MSP430:UINT16_C_(0) (0U)
+// MSP430:INT32_C_(0) (0)
+// MSP430:UINT32_C_(0) (0U)
+// MSP430:INT64_C_(0) INT64_C(0)
+// MSP430:UINT64_C_(0) UINT64_C(0)
+//
+// MSP430:INTMAX_C_(0) (0LL)
+// MSP430:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=pic16-none-none %s | FileCheck -check-prefix PIC16 %s &&
+//
+// PIC16:typedef signed char int8_t;
+// PIC16:typedef short int16_t;
+// PIC16:typedef long long int32_t;
+//
+// PIC16:typedef unsigned char uint8_t;
+// PIC16:typedef int8_t int_least8_t;
+// PIC16:typedef uint8_t uint_least8_t;
+// PIC16:typedef int8_t int_fast8_t;
+// PIC16:typedef uint8_t uint_fast8_t;
+//
+// PIC16:typedef unsigned short uint16_t;
+// PIC16:typedef int16_t int_least16_t;
+// PIC16:typedef uint16_t uint_least16_t;
+// PIC16:typedef int16_t int_fast16_t;
+// PIC16:typedef uint16_t uint_fast16_t;
+//
+// PIC16:typedef unsigned long long uint32_t;
+// PIC16:typedef int32_t int_least32_t;
+// PIC16:typedef uint32_t uint_least32_t;
+// PIC16:typedef int32_t int_fast32_t;
+// PIC16:typedef uint32_t uint_fast32_t;
+//
+// PIC16:typedef short intptr_t;
+// PIC16:typedef unsigned short uintptr_t;
+//
+// PIC16:typedef long int intmax_t;
+// PIC16:typedef long unsigned int uintmax_t;
+//
+// PIC16:INT8_MAX_ 127
+// PIC16:INT8_MIN_ (-128)
+// PIC16:UINT8_MAX_ 255
+// PIC16:INT_LEAST8_MIN_ (-128)
+// PIC16:INT_LEAST8_MAX_ 127
+// PIC16:UINT_LEAST8_MAX_ 255
+// PIC16:INT_FAST8_MIN_ (-128)
+// PIC16:INT_FAST8_MAX_ 127
+// PIC16:UINT_FAST8_MAX_ 255
+//
+// PIC16:INT16_MAX_ 32767
+// PIC16:INT16_MIN_ (-32768)
+// PIC16:UINT16_MAX_ 65535
+// PIC16:INT_LEAST16_MIN_ (-32768)
+// PIC16:INT_LEAST16_MAX_ 32767
+// PIC16:UINT_LEAST16_MAX_ 65535
+// PIC16:INT_FAST16_MIN_ (-32768)
+// PIC16:INT_FAST16_MAX_ 32767
+// PIC16:UINT_FAST16_MAX_ 65535
+//
+// PIC16:INT32_MAX_ 2147483647
+// PIC16:INT32_MIN_ (-2147483647 -1)
+// PIC16:UINT32_MAX_ 4294967295U
+// PIC16:INT_LEAST32_MIN_ (-2147483647 -1)
+// PIC16:INT_LEAST32_MAX_ 2147483647
+// PIC16:UINT_LEAST32_MAX_ 4294967295U
+// PIC16:INT_FAST32_MIN_ (-2147483647 -1)
+// PIC16:INT_FAST32_MAX_ 2147483647
+// PIC16:UINT_FAST32_MAX_ 4294967295U
+//
+// PIC16:INT64_MAX_ INT64_MAX
+// PIC16:INT64_MIN_ INT64_MIN
+// PIC16:UINT64_MAX_ UINT64_MAX
+// PIC16:INT_LEAST64_MIN_ INT_LEAST64_MIN
+// PIC16:INT_LEAST64_MAX_ INT_LEAST64_MAX
+// PIC16:UINT_LEAST64_MAX_ UINT_LEAST64_MAX
+// PIC16:INT_FAST64_MIN_ INT_FAST64_MIN
+// PIC16:INT_FAST64_MAX_ INT_FAST64_MAX
+// PIC16:UINT_FAST64_MAX_ UINT_FAST64_MAX
+//
+// PIC16:INTPTR_MIN_ (-32768)
+// PIC16:INTPTR_MAX_ 32767
+// PIC16:UINTPTR_MAX_ 65535
+// PIC16:PTRDIFF_MIN_ (-32768)
+// PIC16:PTRDIFF_MAX_ 32767
+// PIC16:SIZE_MAX_ 65535
+//
+// PIC16:INTMAX_MIN_ (-2147483647L -1)
+// PIC16:INTMAX_MAX_ 2147483647L
+// PIC16:UINTMAX_MAX_ (2147483647L*2ULL +1ULL)
+//
+// PIC16:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// PIC16:SIG_ATOMIC_MAX_ 2147483647
+// PIC16:WINT_MIN_ (-2147483647 -1)
+// PIC16:WINT_MAX_ 2147483647
+//
+// PIC16:WCHAR_MAX_ 2147483647
+// PIC16:WCHAR_MIN_ (-2147483647 -1)
+//
+// PIC16:INT8_C_(0) (0)
+// PIC16:UINT8_C_(0) (0U)
+// PIC16:INT16_C_(0) (0)
+// PIC16:UINT16_C_(0) (0U)
+// PIC16:INT32_C_(0) (0)
+// PIC16:UINT32_C_(0) (0U)
+// PIC16:INT64_C_(0) INT64_C(0)
+// PIC16:UINT64_C_(0) UINT64_C(0)
+//
+// PIC16:INTMAX_C_(0) (0LL)
+// PIC16:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=powerpc64-none-none %s | FileCheck -check-prefix PPC64 %s &&
+//
+// PPC64:typedef signed char int8_t;
+// PPC64:typedef short int16_t;
+// PPC64:typedef int int32_t;
+// PPC64:typedef long int int64_t;
+//
+// PPC64:typedef unsigned char uint8_t;
+// PPC64:typedef int8_t int_least8_t;
+// PPC64:typedef uint8_t uint_least8_t;
+// PPC64:typedef int8_t int_fast8_t;
+// PPC64:typedef uint8_t uint_fast8_t;
+//
+// PPC64:typedef unsigned short uint16_t;
+// PPC64:typedef int16_t int_least16_t;
+// PPC64:typedef uint16_t uint_least16_t;
+// PPC64:typedef int16_t int_fast16_t;
+// PPC64:typedef uint16_t uint_fast16_t;
+//
+// PPC64:typedef unsigned int uint32_t;
+// PPC64:typedef int32_t int_least32_t;
+// PPC64:typedef uint32_t uint_least32_t;
+// PPC64:typedef int32_t int_fast32_t;
+// PPC64:typedef uint32_t uint_fast32_t;
+//
+// PPC64:typedef unsigned long int uint64_t;
+// PPC64:typedef int64_t int_least64_t;
+// PPC64:typedef uint64_t uint_least64_t;
+// PPC64:typedef int64_t int_fast64_t;
+// PPC64:typedef uint64_t uint_fast64_t;
+//
+// PPC64:typedef long int intptr_t;
+// PPC64:typedef unsigned long int uintptr_t;
+//
+// PPC64:typedef long int intmax_t;
+// PPC64:typedef long unsigned int uintmax_t;
+//
+// PPC64:INT8_MAX_ 127
+// PPC64:INT8_MIN_ (-128)
+// PPC64:UINT8_MAX_ 255
+// PPC64:INT_LEAST8_MIN_ (-128)
+// PPC64:INT_LEAST8_MAX_ 127
+// PPC64:UINT_LEAST8_MAX_ 255
+// PPC64:INT_FAST8_MIN_ (-128)
+// PPC64:INT_FAST8_MAX_ 127
+// PPC64:UINT_FAST8_MAX_ 255
+//
+// PPC64:INT16_MAX_ 32767
+// PPC64:INT16_MIN_ (-32768)
+// PPC64:UINT16_MAX_ 65535
+// PPC64:INT_LEAST16_MIN_ (-32768)
+// PPC64:INT_LEAST16_MAX_ 32767
+// PPC64:UINT_LEAST16_MAX_ 65535
+// PPC64:INT_FAST16_MIN_ (-32768)
+// PPC64:INT_FAST16_MAX_ 32767
+// PPC64:UINT_FAST16_MAX_ 65535
+//
+// PPC64:INT32_MAX_ 2147483647
+// PPC64:INT32_MIN_ (-2147483647 -1)
+// PPC64:UINT32_MAX_ 4294967295U
+// PPC64:INT_LEAST32_MIN_ (-2147483647 -1)
+// PPC64:INT_LEAST32_MAX_ 2147483647
+// PPC64:UINT_LEAST32_MAX_ 4294967295U
+// PPC64:INT_FAST32_MIN_ (-2147483647 -1)
+// PPC64:INT_FAST32_MAX_ 2147483647
+// PPC64:UINT_FAST32_MAX_ 4294967295U
+//
+// PPC64:INT64_MAX_ 9223372036854775807LL
+// PPC64:INT64_MIN_ (-9223372036854775807LL -1)
+// PPC64:UINT64_MAX_ 18446744073709551615ULL
+// PPC64:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// PPC64:INT_LEAST64_MAX_ 9223372036854775807LL
+// PPC64:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// PPC64:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// PPC64:INT_FAST64_MAX_ 9223372036854775807LL
+// PPC64:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// PPC64:INTPTR_MIN_ (-9223372036854775807LL -1)
+// PPC64:INTPTR_MAX_ 9223372036854775807LL
+// PPC64:UINTPTR_MAX_ 18446744073709551615ULL
+// PPC64:PTRDIFF_MIN_ (-9223372036854775807LL -1)
+// PPC64:PTRDIFF_MAX_ 9223372036854775807LL
+// PPC64:SIZE_MAX_ 18446744073709551615ULL
+//
+// PPC64:INTMAX_MIN_ (-9223372036854775807L -1)
+// PPC64:INTMAX_MAX_ 9223372036854775807L
+// PPC64:UINTMAX_MAX_ (9223372036854775807L*2ULL +1ULL)
+//
+// PPC64:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// PPC64:SIG_ATOMIC_MAX_ 2147483647
+// PPC64:WINT_MIN_ (-2147483647 -1)
+// PPC64:WINT_MAX_ 2147483647
+//
+// PPC64:WCHAR_MAX_ 2147483647
+// PPC64:WCHAR_MIN_ (-2147483647 -1)
+//
+// PPC64:INT8_C_(0) (0)
+// PPC64:UINT8_C_(0) (0U)
+// PPC64:INT16_C_(0) (0)
+// PPC64:UINT16_C_(0) (0U)
+// PPC64:INT32_C_(0) (0)
+// PPC64:UINT32_C_(0) (0U)
+// PPC64:INT64_C_(0) (0LL)
+// PPC64:UINT64_C_(0) (0ULL)
+//
+// PPC64:INTMAX_C_(0) (0LL)
+// PPC64:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s &&
+//
+// PPC:typedef signed char int8_t;
+// PPC:typedef short int16_t;
+// PPC:typedef int int32_t;
+// PPC:typedef long long int int64_t;
+//
+// PPC:typedef unsigned char uint8_t;
+// PPC:typedef int8_t int_least8_t;
+// PPC:typedef uint8_t uint_least8_t;
+// PPC:typedef int8_t int_fast8_t;
+// PPC:typedef uint8_t uint_fast8_t;
+//
+// PPC:typedef unsigned short uint16_t;
+// PPC:typedef int16_t int_least16_t;
+// PPC:typedef uint16_t uint_least16_t;
+// PPC:typedef int16_t int_fast16_t;
+// PPC:typedef uint16_t uint_fast16_t;
+//
+// PPC:typedef unsigned int uint32_t;
+// PPC:typedef int32_t int_least32_t;
+// PPC:typedef uint32_t uint_least32_t;
+// PPC:typedef int32_t int_fast32_t;
+// PPC:typedef uint32_t uint_fast32_t;
+//
+// PPC:typedef unsigned long long int uint64_t;
+// PPC:typedef int64_t int_least64_t;
+// PPC:typedef uint64_t uint_least64_t;
+// PPC:typedef int64_t int_fast64_t;
+// PPC:typedef uint64_t uint_fast64_t;
+//
+// PPC:typedef long int intptr_t;
+// PPC:typedef unsigned long int uintptr_t;
+//
+// PPC:typedef long long int intmax_t;
+// PPC:typedef long long unsigned int uintmax_t;
+//
+// PPC:INT8_MAX_ 127
+// PPC:INT8_MIN_ (-128)
+// PPC:UINT8_MAX_ 255
+// PPC:INT_LEAST8_MIN_ (-128)
+// PPC:INT_LEAST8_MAX_ 127
+// PPC:UINT_LEAST8_MAX_ 255
+// PPC:INT_FAST8_MIN_ (-128)
+// PPC:INT_FAST8_MAX_ 127
+// PPC:UINT_FAST8_MAX_ 255
+//
+// PPC:INT16_MAX_ 32767
+// PPC:INT16_MIN_ (-32768)
+// PPC:UINT16_MAX_ 65535
+// PPC:INT_LEAST16_MIN_ (-32768)
+// PPC:INT_LEAST16_MAX_ 32767
+// PPC:UINT_LEAST16_MAX_ 65535
+// PPC:INT_FAST16_MIN_ (-32768)
+// PPC:INT_FAST16_MAX_ 32767
+// PPC:UINT_FAST16_MAX_ 65535
+//
+// PPC:INT32_MAX_ 2147483647
+// PPC:INT32_MIN_ (-2147483647 -1)
+// PPC:UINT32_MAX_ 4294967295U
+// PPC:INT_LEAST32_MIN_ (-2147483647 -1)
+// PPC:INT_LEAST32_MAX_ 2147483647
+// PPC:UINT_LEAST32_MAX_ 4294967295U
+// PPC:INT_FAST32_MIN_ (-2147483647 -1)
+// PPC:INT_FAST32_MAX_ 2147483647
+// PPC:UINT_FAST32_MAX_ 4294967295U
+//
+// PPC:INT64_MAX_ 9223372036854775807LL
+// PPC:INT64_MIN_ (-9223372036854775807LL -1)
+// PPC:UINT64_MAX_ 18446744073709551615ULL
+// PPC:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// PPC:INT_LEAST64_MAX_ 9223372036854775807LL
+// PPC:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// PPC:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// PPC:INT_FAST64_MAX_ 9223372036854775807LL
+// PPC:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// PPC:INTPTR_MIN_ (-2147483647 -1)
+// PPC:INTPTR_MAX_ 2147483647
+// PPC:UINTPTR_MAX_ 4294967295U
+// PPC:PTRDIFF_MIN_ (-2147483647 -1)
+// PPC:PTRDIFF_MAX_ 2147483647
+// PPC:SIZE_MAX_ 4294967295U
+//
+// PPC:INTMAX_MIN_ (-9223372036854775807LL -1)
+// PPC:INTMAX_MAX_ 9223372036854775807LL
+// PPC:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// PPC:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// PPC:SIG_ATOMIC_MAX_ 2147483647
+// PPC:WINT_MIN_ (-2147483647 -1)
+// PPC:WINT_MAX_ 2147483647
+//
+// PPC:WCHAR_MAX_ 2147483647
+// PPC:WCHAR_MIN_ (-2147483647 -1)
+//
+// PPC:INT8_C_(0) (0)
+// PPC:UINT8_C_(0) (0U)
+// PPC:INT16_C_(0) (0)
+// PPC:UINT16_C_(0) (0U)
+// PPC:INT32_C_(0) (0)
+// PPC:UINT32_C_(0) (0U)
+// PPC:INT64_C_(0) (0LL)
+// PPC:UINT64_C_(0) (0ULL)
+//
+// PPC:INTMAX_C_(0) (0LL)
+// PPC:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=s390x-none-none %s | FileCheck -check-prefix S390X %s &&
+//
+// S390X:typedef signed char int8_t;
+// S390X:typedef short int16_t;
+// S390X:typedef int int32_t;
+// S390X:typedef long long int int64_t;
+//
+// S390X:typedef unsigned char uint8_t;
+// S390X:typedef int8_t int_least8_t;
+// S390X:typedef uint8_t uint_least8_t;
+// S390X:typedef int8_t int_fast8_t;
+// S390X:typedef uint8_t uint_fast8_t;
+//
+// S390X:typedef unsigned short uint16_t;
+// S390X:typedef int16_t int_least16_t;
+// S390X:typedef uint16_t uint_least16_t;
+// S390X:typedef int16_t int_fast16_t;
+// S390X:typedef uint16_t uint_fast16_t;
+//
+// S390X:typedef unsigned int uint32_t;
+// S390X:typedef int32_t int_least32_t;
+// S390X:typedef uint32_t uint_least32_t;
+// S390X:typedef int32_t int_fast32_t;
+// S390X:typedef uint32_t uint_fast32_t;
+//
+// S390X:typedef unsigned long long int uint64_t;
+// S390X:typedef int64_t int_least64_t;
+// S390X:typedef uint64_t uint_least64_t;
+// S390X:typedef int64_t int_fast64_t;
+// S390X:typedef uint64_t uint_fast64_t;
+//
+// S390X:typedef long int intptr_t;
+// S390X:typedef unsigned long int uintptr_t;
+//
+// S390X:typedef long long int intmax_t;
+// S390X:typedef long long unsigned int uintmax_t;
+//
+// S390X:INT8_MAX_ 127
+// S390X:INT8_MIN_ (-128)
+// S390X:UINT8_MAX_ 255
+// S390X:INT_LEAST8_MIN_ (-128)
+// S390X:INT_LEAST8_MAX_ 127
+// S390X:UINT_LEAST8_MAX_ 255
+// S390X:INT_FAST8_MIN_ (-128)
+// S390X:INT_FAST8_MAX_ 127
+// S390X:UINT_FAST8_MAX_ 255
+//
+// S390X:INT16_MAX_ 32767
+// S390X:INT16_MIN_ (-32768)
+// S390X:UINT16_MAX_ 65535
+// S390X:INT_LEAST16_MIN_ (-32768)
+// S390X:INT_LEAST16_MAX_ 32767
+// S390X:UINT_LEAST16_MAX_ 65535
+// S390X:INT_FAST16_MIN_ (-32768)
+// S390X:INT_FAST16_MAX_ 32767
+// S390X:UINT_FAST16_MAX_ 65535
+//
+// S390X:INT32_MAX_ 2147483647
+// S390X:INT32_MIN_ (-2147483647 -1)
+// S390X:UINT32_MAX_ 4294967295U
+// S390X:INT_LEAST32_MIN_ (-2147483647 -1)
+// S390X:INT_LEAST32_MAX_ 2147483647
+// S390X:UINT_LEAST32_MAX_ 4294967295U
+// S390X:INT_FAST32_MIN_ (-2147483647 -1)
+// S390X:INT_FAST32_MAX_ 2147483647
+// S390X:UINT_FAST32_MAX_ 4294967295U
+//
+// S390X:INT64_MAX_ 9223372036854775807LL
+// S390X:INT64_MIN_ (-9223372036854775807LL -1)
+// S390X:UINT64_MAX_ 18446744073709551615ULL
+// S390X:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// S390X:INT_LEAST64_MAX_ 9223372036854775807LL
+// S390X:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// S390X:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// S390X:INT_FAST64_MAX_ 9223372036854775807LL
+// S390X:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// S390X:INTPTR_MIN_ (-9223372036854775807LL -1)
+// S390X:INTPTR_MAX_ 9223372036854775807LL
+// S390X:UINTPTR_MAX_ 18446744073709551615ULL
+// S390X:PTRDIFF_MIN_ (-9223372036854775807LL -1)
+// S390X:PTRDIFF_MAX_ 9223372036854775807LL
+// S390X:SIZE_MAX_ 18446744073709551615ULL
+//
+// S390X:INTMAX_MIN_ (-9223372036854775807LL -1)
+// S390X:INTMAX_MAX_ 9223372036854775807LL
+// S390X:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// S390X:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// S390X:SIG_ATOMIC_MAX_ 2147483647
+// S390X:WINT_MIN_ (-2147483647 -1)
+// S390X:WINT_MAX_ 2147483647
+//
+// S390X:WCHAR_MAX_ 2147483647
+// S390X:WCHAR_MIN_ (-2147483647 -1)
+//
+// S390X:INT8_C_(0) (0)
+// S390X:UINT8_C_(0) (0U)
+// S390X:INT16_C_(0) (0)
+// S390X:UINT16_C_(0) (0U)
+// S390X:INT32_C_(0) (0)
+// S390X:UINT32_C_(0) (0U)
+// S390X:INT64_C_(0) (0LL)
+// S390X:UINT64_C_(0) (0ULL)
+//
+// S390X:INTMAX_C_(0) (0LL)
+// S390X:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=sparc-none-none %s | FileCheck -check-prefix SPARC %s &&
+//
+// SPARC:typedef signed char int8_t;
+// SPARC:typedef short int16_t;
+// SPARC:typedef int int32_t;
+// SPARC:typedef long long int int64_t;
+//
+// SPARC:typedef unsigned char uint8_t;
+// SPARC:typedef int8_t int_least8_t;
+// SPARC:typedef uint8_t uint_least8_t;
+// SPARC:typedef int8_t int_fast8_t;
+// SPARC:typedef uint8_t uint_fast8_t;
+//
+// SPARC:typedef unsigned short uint16_t;
+// SPARC:typedef int16_t int_least16_t;
+// SPARC:typedef uint16_t uint_least16_t;
+// SPARC:typedef int16_t int_fast16_t;
+// SPARC:typedef uint16_t uint_fast16_t;
+//
+// SPARC:typedef unsigned int uint32_t;
+// SPARC:typedef int32_t int_least32_t;
+// SPARC:typedef uint32_t uint_least32_t;
+// SPARC:typedef int32_t int_fast32_t;
+// SPARC:typedef uint32_t uint_fast32_t;
+//
+// SPARC:typedef unsigned long long int uint64_t;
+// SPARC:typedef int64_t int_least64_t;
+// SPARC:typedef uint64_t uint_least64_t;
+// SPARC:typedef int64_t int_fast64_t;
+// SPARC:typedef uint64_t uint_fast64_t;
+//
+// SPARC:typedef long int intptr_t;
+// SPARC:typedef unsigned long int uintptr_t;
+//
+// SPARC:typedef long long int intmax_t;
+// SPARC:typedef long long unsigned int uintmax_t;
+//
+// SPARC:INT8_MAX_ 127
+// SPARC:INT8_MIN_ (-128)
+// SPARC:UINT8_MAX_ 255
+// SPARC:INT_LEAST8_MIN_ (-128)
+// SPARC:INT_LEAST8_MAX_ 127
+// SPARC:UINT_LEAST8_MAX_ 255
+// SPARC:INT_FAST8_MIN_ (-128)
+// SPARC:INT_FAST8_MAX_ 127
+// SPARC:UINT_FAST8_MAX_ 255
+//
+// SPARC:INT16_MAX_ 32767
+// SPARC:INT16_MIN_ (-32768)
+// SPARC:UINT16_MAX_ 65535
+// SPARC:INT_LEAST16_MIN_ (-32768)
+// SPARC:INT_LEAST16_MAX_ 32767
+// SPARC:UINT_LEAST16_MAX_ 65535
+// SPARC:INT_FAST16_MIN_ (-32768)
+// SPARC:INT_FAST16_MAX_ 32767
+// SPARC:UINT_FAST16_MAX_ 65535
+//
+// SPARC:INT32_MAX_ 2147483647
+// SPARC:INT32_MIN_ (-2147483647 -1)
+// SPARC:UINT32_MAX_ 4294967295U
+// SPARC:INT_LEAST32_MIN_ (-2147483647 -1)
+// SPARC:INT_LEAST32_MAX_ 2147483647
+// SPARC:UINT_LEAST32_MAX_ 4294967295U
+// SPARC:INT_FAST32_MIN_ (-2147483647 -1)
+// SPARC:INT_FAST32_MAX_ 2147483647
+// SPARC:UINT_FAST32_MAX_ 4294967295U
+//
+// SPARC:INT64_MAX_ 9223372036854775807LL
+// SPARC:INT64_MIN_ (-9223372036854775807LL -1)
+// SPARC:UINT64_MAX_ 18446744073709551615ULL
+// SPARC:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// SPARC:INT_LEAST64_MAX_ 9223372036854775807LL
+// SPARC:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// SPARC:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// SPARC:INT_FAST64_MAX_ 9223372036854775807LL
+// SPARC:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// SPARC:INTPTR_MIN_ (-2147483647 -1)
+// SPARC:INTPTR_MAX_ 2147483647
+// SPARC:UINTPTR_MAX_ 4294967295U
+// SPARC:PTRDIFF_MIN_ (-2147483647 -1)
+// SPARC:PTRDIFF_MAX_ 2147483647
+// SPARC:SIZE_MAX_ 4294967295U
+//
+// SPARC:INTMAX_MIN_ (-9223372036854775807LL -1)
+// SPARC:INTMAX_MAX_ 9223372036854775807LL
+// SPARC:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL)
+//
+// SPARC:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// SPARC:SIG_ATOMIC_MAX_ 2147483647
+// SPARC:WINT_MIN_ (-2147483647 -1)
+// SPARC:WINT_MAX_ 2147483647
+//
+// SPARC:WCHAR_MAX_ 2147483647
+// SPARC:WCHAR_MIN_ (-2147483647 -1)
+//
+// SPARC:INT8_C_(0) (0)
+// SPARC:UINT8_C_(0) (0U)
+// SPARC:INT16_C_(0) (0)
+// SPARC:UINT16_C_(0) (0U)
+// SPARC:INT32_C_(0) (0)
+// SPARC:UINT32_C_(0) (0U)
+// SPARC:INT64_C_(0) (0LL)
+// SPARC:UINT64_C_(0) (0ULL)
+//
+// SPARC:INTMAX_C_(0) (0LL)
+// SPARC:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=tce-none-none %s | FileCheck -check-prefix TCE %s &&
+//
+// TCE:typedef signed char int8_t;
+// TCE:typedef short int16_t;
+// TCE:typedef int int32_t;
+//
+// TCE:typedef unsigned char uint8_t;
+// TCE:typedef int8_t int_least8_t;
+// TCE:typedef uint8_t uint_least8_t;
+// TCE:typedef int8_t int_fast8_t;
+// TCE:typedef uint8_t uint_fast8_t;
+//
+// TCE:typedef unsigned short uint16_t;
+// TCE:typedef int16_t int_least16_t;
+// TCE:typedef uint16_t uint_least16_t;
+// TCE:typedef int16_t int_fast16_t;
+// TCE:typedef uint16_t uint_fast16_t;
+//
+// TCE:typedef unsigned int uint32_t;
+// TCE:typedef int32_t int_least32_t;
+// TCE:typedef uint32_t uint_least32_t;
+// TCE:typedef int32_t int_fast32_t;
+// TCE:typedef uint32_t uint_fast32_t;
+//
+// TCE:typedef int intptr_t;
+// TCE:typedef unsigned int uintptr_t;
+//
+// TCE:typedef long int intmax_t;
+// TCE:typedef long unsigned int uintmax_t;
+//
+// TCE:INT8_MAX_ 127
+// TCE:INT8_MIN_ (-128)
+// TCE:UINT8_MAX_ 255
+// TCE:INT_LEAST8_MIN_ (-128)
+// TCE:INT_LEAST8_MAX_ 127
+// TCE:UINT_LEAST8_MAX_ 255
+// TCE:INT_FAST8_MIN_ (-128)
+// TCE:INT_FAST8_MAX_ 127
+// TCE:UINT_FAST8_MAX_ 255
+//
+// TCE:INT16_MAX_ 32767
+// TCE:INT16_MIN_ (-32768)
+// TCE:UINT16_MAX_ 65535
+// TCE:INT_LEAST16_MIN_ (-32768)
+// TCE:INT_LEAST16_MAX_ 32767
+// TCE:UINT_LEAST16_MAX_ 65535
+// TCE:INT_FAST16_MIN_ (-32768)
+// TCE:INT_FAST16_MAX_ 32767
+// TCE:UINT_FAST16_MAX_ 65535
+//
+// TCE:INT32_MAX_ 2147483647
+// TCE:INT32_MIN_ (-2147483647 -1)
+// TCE:UINT32_MAX_ 4294967295U
+// TCE:INT_LEAST32_MIN_ (-2147483647 -1)
+// TCE:INT_LEAST32_MAX_ 2147483647
+// TCE:UINT_LEAST32_MAX_ 4294967295U
+// TCE:INT_FAST32_MIN_ (-2147483647 -1)
+// TCE:INT_FAST32_MAX_ 2147483647
+// TCE:UINT_FAST32_MAX_ 4294967295U
+//
+// TCE:INT64_MAX_ INT64_MAX
+// TCE:INT64_MIN_ INT64_MIN
+// TCE:UINT64_MAX_ UINT64_MAX
+// TCE:INT_LEAST64_MIN_ INT_LEAST64_MIN
+// TCE:INT_LEAST64_MAX_ INT_LEAST64_MAX
+// TCE:UINT_LEAST64_MAX_ UINT_LEAST64_MAX
+// TCE:INT_FAST64_MIN_ INT_FAST64_MIN
+// TCE:INT_FAST64_MAX_ INT_FAST64_MAX
+// TCE:UINT_FAST64_MAX_ UINT_FAST64_MAX
+//
+// TCE:INTPTR_MIN_ (-2147483647 -1)
+// TCE:INTPTR_MAX_ 2147483647
+// TCE:UINTPTR_MAX_ 4294967295U
+// TCE:PTRDIFF_MIN_ (-2147483647 -1)
+// TCE:PTRDIFF_MAX_ 2147483647
+// TCE:SIZE_MAX_ 4294967295U
+//
+// TCE:INTMAX_MIN_ (-2147483647L -1)
+// TCE:INTMAX_MAX_ 2147483647L
+// TCE:UINTMAX_MAX_ (2147483647L*2ULL +1ULL)
+//
+// TCE:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// TCE:SIG_ATOMIC_MAX_ 2147483647
+// TCE:WINT_MIN_ (-2147483647 -1)
+// TCE:WINT_MAX_ 2147483647
+//
+// TCE:WCHAR_MAX_ 2147483647
+// TCE:WCHAR_MIN_ (-2147483647 -1)
+//
+// TCE:INT8_C_(0) (0)
+// TCE:UINT8_C_(0) (0U)
+// TCE:INT16_C_(0) (0)
+// TCE:UINT16_C_(0) (0U)
+// TCE:INT32_C_(0) (0)
+// TCE:UINT32_C_(0) (0U)
+// TCE:INT64_C_(0) INT64_C(0)
+// TCE:UINT64_C_(0) UINT64_C(0)
+//
+// TCE:INTMAX_C_(0) (0LL)
+// TCE:UINTMAX_C_(0) (0ULL)
+//
+// RUN: clang-cc -E -ffreestanding -triple=x86_64-none-none %s | FileCheck -check-prefix X86_64 %s &&
+//
+// X86_64:typedef signed char int8_t;
+// X86_64:typedef short int16_t;
+// X86_64:typedef int int32_t;
+// X86_64:typedef long int int64_t;
+//
+// X86_64:typedef unsigned char uint8_t;
+// X86_64:typedef int8_t int_least8_t;
+// X86_64:typedef uint8_t uint_least8_t;
+// X86_64:typedef int8_t int_fast8_t;
+// X86_64:typedef uint8_t uint_fast8_t;
+//
+// X86_64:typedef unsigned short uint16_t;
+// X86_64:typedef int16_t int_least16_t;
+// X86_64:typedef uint16_t uint_least16_t;
+// X86_64:typedef int16_t int_fast16_t;
+// X86_64:typedef uint16_t uint_fast16_t;
+//
+// X86_64:typedef unsigned int uint32_t;
+// X86_64:typedef int32_t int_least32_t;
+// X86_64:typedef uint32_t uint_least32_t;
+// X86_64:typedef int32_t int_fast32_t;
+// X86_64:typedef uint32_t uint_fast32_t;
+//
+// X86_64:typedef unsigned long int uint64_t;
+// X86_64:typedef int64_t int_least64_t;
+// X86_64:typedef uint64_t uint_least64_t;
+// X86_64:typedef int64_t int_fast64_t;
+// X86_64:typedef uint64_t uint_fast64_t;
+//
+// X86_64:typedef long int intptr_t;
+// X86_64:typedef unsigned long int uintptr_t;
+//
+// X86_64:typedef long int intmax_t;
+// X86_64:typedef long unsigned int uintmax_t;
+//
+// X86_64:INT8_MAX_ 127
+// X86_64:INT8_MIN_ (-128)
+// X86_64:UINT8_MAX_ 255
+// X86_64:INT_LEAST8_MIN_ (-128)
+// X86_64:INT_LEAST8_MAX_ 127
+// X86_64:UINT_LEAST8_MAX_ 255
+// X86_64:INT_FAST8_MIN_ (-128)
+// X86_64:INT_FAST8_MAX_ 127
+// X86_64:UINT_FAST8_MAX_ 255
+//
+// X86_64:INT16_MAX_ 32767
+// X86_64:INT16_MIN_ (-32768)
+// X86_64:UINT16_MAX_ 65535
+// X86_64:INT_LEAST16_MIN_ (-32768)
+// X86_64:INT_LEAST16_MAX_ 32767
+// X86_64:UINT_LEAST16_MAX_ 65535
+// X86_64:INT_FAST16_MIN_ (-32768)
+// X86_64:INT_FAST16_MAX_ 32767
+// X86_64:UINT_FAST16_MAX_ 65535
+//
+// X86_64:INT32_MAX_ 2147483647
+// X86_64:INT32_MIN_ (-2147483647 -1)
+// X86_64:UINT32_MAX_ 4294967295U
+// X86_64:INT_LEAST32_MIN_ (-2147483647 -1)
+// X86_64:INT_LEAST32_MAX_ 2147483647
+// X86_64:UINT_LEAST32_MAX_ 4294967295U
+// X86_64:INT_FAST32_MIN_ (-2147483647 -1)
+// X86_64:INT_FAST32_MAX_ 2147483647
+// X86_64:UINT_FAST32_MAX_ 4294967295U
+//
+// X86_64:INT64_MAX_ 9223372036854775807LL
+// X86_64:INT64_MIN_ (-9223372036854775807LL -1)
+// X86_64:UINT64_MAX_ 18446744073709551615ULL
+// X86_64:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
+// X86_64:INT_LEAST64_MAX_ 9223372036854775807LL
+// X86_64:UINT_LEAST64_MAX_ 18446744073709551615ULL
+// X86_64:INT_FAST64_MIN_ (-9223372036854775807LL -1)
+// X86_64:INT_FAST64_MAX_ 9223372036854775807LL
+// X86_64:UINT_FAST64_MAX_ 18446744073709551615ULL
+//
+// X86_64:INTPTR_MIN_ (-9223372036854775807LL -1)
+// X86_64:INTPTR_MAX_ 9223372036854775807LL
+// X86_64:UINTPTR_MAX_ 18446744073709551615ULL
+// X86_64:PTRDIFF_MIN_ (-9223372036854775807LL -1)
+// X86_64:PTRDIFF_MAX_ 9223372036854775807LL
+// X86_64:SIZE_MAX_ 18446744073709551615ULL
+//
+// X86_64:INTMAX_MIN_ (-9223372036854775807L -1)
+// X86_64:INTMAX_MAX_ 9223372036854775807L
+// X86_64:UINTMAX_MAX_ (9223372036854775807L*2ULL +1ULL)
+//
+// X86_64:SIG_ATOMIC_MIN_ (-2147483647 -1)
+// X86_64:SIG_ATOMIC_MAX_ 2147483647
+// X86_64:WINT_MIN_ (-2147483647 -1)
+// X86_64:WINT_MAX_ 2147483647
+//
+// X86_64:WCHAR_MAX_ 2147483647
+// X86_64:WCHAR_MIN_ (-2147483647 -1)
+//
+// X86_64:INT8_C_(0) (0)
+// X86_64:UINT8_C_(0) (0U)
+// X86_64:INT16_C_(0) (0)
+// X86_64:UINT16_C_(0) (0U)
+// X86_64:INT32_C_(0) (0)
+// X86_64:UINT32_C_(0) (0U)
+// X86_64:INT64_C_(0) (0LL)
+// X86_64:UINT64_C_(0) (0ULL)
+//
+// X86_64:INTMAX_C_(0) (0LL)
+// X86_64:UINTMAX_C_(0) (0ULL)
+//
+// RUN: true
+
+#include <stdint.h>
+
+INT8_MAX_ INT8_MAX
+INT8_MIN_ INT8_MIN
+UINT8_MAX_ UINT8_MAX
+INT_LEAST8_MIN_ INT_LEAST8_MIN
+INT_LEAST8_MAX_ INT_LEAST8_MAX
+UINT_LEAST8_MAX_ UINT_LEAST8_MAX
+INT_FAST8_MIN_ INT_FAST8_MIN
+INT_FAST8_MAX_ INT_FAST8_MAX
+UINT_FAST8_MAX_ UINT_FAST8_MAX
+
+INT16_MAX_ INT16_MAX
+INT16_MIN_ INT16_MIN
+UINT16_MAX_ UINT16_MAX
+INT_LEAST16_MIN_ INT_LEAST16_MIN
+INT_LEAST16_MAX_ INT_LEAST16_MAX
+UINT_LEAST16_MAX_ UINT_LEAST16_MAX
+INT_FAST16_MIN_ INT_FAST16_MIN
+INT_FAST16_MAX_ INT_FAST16_MAX
+UINT_FAST16_MAX_ UINT_FAST16_MAX
+
+INT32_MAX_ INT32_MAX
+INT32_MIN_ INT32_MIN
+UINT32_MAX_ UINT32_MAX
+INT_LEAST32_MIN_ INT_LEAST32_MIN
+INT_LEAST32_MAX_ INT_LEAST32_MAX
+UINT_LEAST32_MAX_ UINT_LEAST32_MAX
+INT_FAST32_MIN_ INT_FAST32_MIN
+INT_FAST32_MAX_ INT_FAST32_MAX
+UINT_FAST32_MAX_ UINT_FAST32_MAX
+
+INT64_MAX_ INT64_MAX
+INT64_MIN_ INT64_MIN
+UINT64_MAX_ UINT64_MAX
+INT_LEAST64_MIN_ INT_LEAST64_MIN
+INT_LEAST64_MAX_ INT_LEAST64_MAX
+UINT_LEAST64_MAX_ UINT_LEAST64_MAX
+INT_FAST64_MIN_ INT_FAST64_MIN
+INT_FAST64_MAX_ INT_FAST64_MAX
+UINT_FAST64_MAX_ UINT_FAST64_MAX
+
+INTPTR_MIN_ INTPTR_MIN
+INTPTR_MAX_ INTPTR_MAX
+UINTPTR_MAX_ UINTPTR_MAX
+PTRDIFF_MIN_ PTRDIFF_MIN
+PTRDIFF_MAX_ PTRDIFF_MAX
+SIZE_MAX_ SIZE_MAX
+
+INTMAX_MIN_ INTMAX_MIN
+INTMAX_MAX_ INTMAX_MAX
+UINTMAX_MAX_ UINTMAX_MAX
+
+SIG_ATOMIC_MIN_ SIG_ATOMIC_MIN
+SIG_ATOMIC_MAX_ SIG_ATOMIC_MAX
+WINT_MIN_ WINT_MIN
+WINT_MAX_ WINT_MAX
+
+WCHAR_MAX_ WCHAR_MAX
+WCHAR_MIN_ WCHAR_MIN
+
+INT8_C_(0) INT8_C(0)
+UINT8_C_(0) UINT8_C(0)
+INT16_C_(0) INT16_C(0)
+UINT16_C_(0) UINT16_C(0)
+INT32_C_(0) INT32_C(0)
+UINT32_C_(0) UINT32_C(0)
+INT64_C_(0) INT64_C(0)
+UINT64_C_(0) UINT64_C(0)
+
+INTMAX_C_(0) INTMAX_C(0)
+UINTMAX_C_(0) UINTMAX_C(0)
diff --git a/test/Preprocessor/stringize_misc.c b/test/Preprocessor/stringize_misc.c
index 251116acad66..60d66a0061f6 100644
--- a/test/Preprocessor/stringize_misc.c
+++ b/test/Preprocessor/stringize_misc.c
@@ -1,20 +1,23 @@
-// RUN: clang-cc -E %s | grep -F '"f(1, 2)" "g((x=y++, y))"' &&
-// RUN: clang-cc -E %s | grep -F '"{a=1" "b=2;}"' &&
-// RUN: clang-cc -E %s | grep -F '"<" "["' &&
-// RUN: clang-cc -E %s | grep -F '"(,)" "(...)"' &&
-// RUN: clang-cc -E %s | grep -F '{a=1 c=3; b=2;}' &&
-// RUN: clang-cc -E %s | grep -F '"a COMMA b" "(a, b)"'
+// RUN: clang-cc -E %s | FileCheck -strict-whitespace %s
#define M(x, y) #x #y
M( f(1, 2), g((x=y++, y)))
+// CHECK: "f(1, 2)" "g((x=y++, y))"
+
M( {a=1 , b=2;} ) /* A semicolon is not a comma */
+// CHECK: "{a=1" "b=2;}"
+
M( <, [ ) /* Passes the arguments < and [ */
+// CHECK: "<" "["
+
M( (,), (...) ) /* Passes the arguments (,) and (...) */
+// CHECK: "(,)" "(...)"
#define START_END(start, end) start c=3; end
START_END( {a=1 , b=2;} ) /* braces are not parentheses */
+// CHECK: {a=1 c=3; b=2;}
/*
* To pass a comma token as an argument it is
@@ -23,4 +26,5 @@ START_END( {a=1 , b=2;} ) /* braces are not parentheses */
#define COMMA ,
M(a COMMA b, (a, b))
+// CHECK: "a COMMA b" "(a, b)"
diff --git a/test/Sema/attr-deprecated.c b/test/Sema/attr-deprecated.c
index e15381e4c6d1..4b889fc8aa4f 100644
--- a/test/Sema/attr-deprecated.c
+++ b/test/Sema/attr-deprecated.c
@@ -43,3 +43,60 @@ void test1(struct foo *F) {
typedef struct foo foo_dep __attribute__((deprecated));
foo_dep *test2; // expected-warning {{'foo_dep' is deprecated}}
+
+struct bar_dep __attribute__((deprecated,
+ invalid_attribute)); // expected-warning {{'invalid_attribute' attribute ignored}}
+
+struct bar_dep *test3; // expected-warning {{'bar_dep' is deprecated}}
+
+
+// These should not warn because the actually declaration itself is deprecated.
+// rdar://6756623
+foo_dep *test4 __attribute__((deprecated));
+struct bar_dep *test5 __attribute__((deprecated));
+
+typedef foo_dep test6(struct bar_dep*); // expected-warning {{'foo_dep' is deprecated}} \
+ // expected-warning {{'bar_dep' is deprecated}}
+typedef foo_dep test7(struct bar_dep*) __attribute__((deprecated));
+
+int test8(char *p) {
+ p += sizeof(foo_dep); // expected-warning {{'foo_dep' is deprecated}}
+
+ foo_dep *ptr; // expected-warning {{'foo_dep' is deprecated}}
+ ptr = (foo_dep*) p; // expected-warning {{'foo_dep' is deprecated}}
+
+ int func(foo_dep *foo); // expected-warning {{'foo_dep' is deprecated}}
+ return func(ptr);
+}
+
+foo_dep *test9(void) __attribute__((deprecated));
+foo_dep *test9(void) {
+ void* myalloc(unsigned long);
+
+ foo_dep *ptr
+ = (foo_dep*)
+ myalloc(sizeof(foo_dep));
+ return ptr;
+}
+
+void test10(void) __attribute__((deprecated));
+void test10(void) {
+ if (sizeof(foo_dep) == sizeof(void*)) {
+ }
+ foo_dep *localfunc(void);
+ foo_dep localvar;
+}
+
+char test11[sizeof(foo_dep)] __attribute__((deprecated));
+char test12[sizeof(foo_dep)]; // expected-warning {{'foo_dep' is deprecated}}
+
+int test13(foo_dep *foo) __attribute__((deprecated));
+int test14(foo_dep *foo); // expected-warning {{'foo_dep' is deprecated}}
+
+unsigned long test15 = sizeof(foo_dep); // expected-warning {{'foo_dep' is deprecated}}
+unsigned long test16 __attribute__((deprecated))
+ = sizeof(foo_dep);
+
+foo_dep test17, // expected-warning {{'foo_dep' is deprecated}}
+ test18 __attribute__((deprecated)),
+ test19;
diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c
index cb69c59c403a..102115b3bf2b 100644
--- a/test/Sema/callingconv.c
+++ b/test/Sema/callingconv.c
@@ -8,3 +8,12 @@ void __attribute__((stdcall)) bar(float *a) {
void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{attribute requires 0 argument(s)}}
}
+
+void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use 'fastcall' calling convention}}
+}
+
+void __attribute__((fastcall)) test1(void) {
+}
+
+void __attribute__((fastcall)) test2(int a, ...) { // expected-error {{variadic function cannot use 'fastcall' calling convention}}
+}
diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c
index 146d9e9bb92b..18dbb1e7c54a 100644
--- a/test/Sema/constant-builtins-2.c
+++ b/test/Sema/constant-builtins-2.c
@@ -48,3 +48,5 @@ extern int f();
int h0 = __builtin_types_compatible_p(int, float);
//int h1 = __builtin_choose_expr(1, 10, f());
//int h2 = __builtin_expect(0, 0);
+extern long int bi0;
+extern __typeof__(__builtin_expect(0, 0)) bi0;
diff --git a/test/Sema/decl-invalid.c b/test/Sema/decl-invalid.c
index 051f0f7ffbcc..823551f02e6f 100644
--- a/test/Sema/decl-invalid.c
+++ b/test/Sema/decl-invalid.c
@@ -10,8 +10,7 @@ int a() {
int r[x()]; // expected-error {{size of array has non-integer type 'void'}}
static y ?; // expected-error{{unknown type name 'y'}} \
- expected-error{{expected identifier or '('}} \
- expected-error{{expected ';' at end of declaration}}
+ expected-error{{expected identifier or '('}}
}
int; // expected-error {{declaration does not declare anything}}
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index 1826c7457e30..797e53c1bd22 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -8,6 +8,10 @@
char * global_fmt;
+#if defined(_WIN32) || defined(_WIN64)
+extern int snprintf(char*, size_t, const char*, ...);
+#endif
+
void check_string_literal( FILE* fp, const char* s, char *buf, ... ) {
char * b;
@@ -83,7 +87,7 @@ void check_wide_string(char* b, ...)
va_start(ap,b);
printf(L"foo %d",2); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}}
- vasprintf(&b,L"bar %d",ap); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}}
+ vsprintf(b,L"bar %d",ap); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}}
}
void check_asterisk_precision_width(int x) {
diff --git a/test/Sema/init.c b/test/Sema/init.c
index 1cbcbb7e36f8..840b24fd30b0 100644
--- a/test/Sema/init.c
+++ b/test/Sema/init.c
@@ -21,7 +21,7 @@ int *h = &x;
int test() {
int a[10];
int b[10] = a; // expected-error {{initialization with '{...}' expected}}
-int +; // expected-error {{expected identifier or '('}} expected-error {{expected ';' at end of declaration}}
+int +; // expected-error {{expected identifier or '('}}
}
diff --git a/test/Sema/offsetof.c b/test/Sema/offsetof.c
index f8b9fed03c3c..dfae99216f8a 100644
--- a/test/Sema/offsetof.c
+++ b/test/Sema/offsetof.c
@@ -48,3 +48,9 @@ int a[__builtin_offsetof(struct sockaddr_un, sun_path[len+1])];
// PR4079
union x {struct {int x;};};
int x[__builtin_offsetof(union x, x)];
+
+// rdar://problem/7222956
+struct incomplete; // expected-note 2 {{forward declaration of 'struct incomplete'}}
+int test1[__builtin_offsetof(struct incomplete, foo)]; // expected-error {{offsetof of incomplete type 'struct incomplete'}}
+
+int test1[__builtin_offsetof(struct incomplete[10], [4].foo)]; // expected-error {{array has incomplete element type 'struct incomplete'}}
diff --git a/test/Sema/parentheses.c b/test/Sema/parentheses.c
new file mode 100644
index 000000000000..a8ad260bf8b5
--- /dev/null
+++ b/test/Sema/parentheses.c
@@ -0,0 +1,20 @@
+// RUN: clang-cc -Wparentheses -fsyntax-only -verify %s &&
+// RUN: clang-cc -Wparentheses -fixit %s -o - | clang-cc -Wparentheses -Werror -
+
+// Test the various warnings under -Wparentheses
+void if_assign(void) {
+ int i;
+ if (i = 4) {} // expected-warning {{assignment as a condition}}
+ if ((i = 4)) {}
+}
+
+void bitwise_rel(unsigned i) {
+ (void)(i & 0x2 == 0); // expected-warning {{& has lower precedence than ==}}
+ (void)(0 == i & 0x2); // expected-warning {{& has lower precedence than ==}}
+ (void)(i & 0xff < 30); // expected-warning {{& has lower precedence than <}}
+ (void)((i & 0x2) == 0);
+ (void)(i & (0x2 == 0));
+ // Eager logical op
+ (void)(i == 1 | i == 2 | i == 3);
+ (void)(i != 1 & i != 2 & i != 3);
+}
diff --git a/test/Sema/return-noreturn.c b/test/Sema/return-noreturn.c
index e2452f407f4f..8868c9ee0aeb 100644
--- a/test/Sema/return-noreturn.c
+++ b/test/Sema/return-noreturn.c
@@ -27,3 +27,11 @@ __attribute__((__noreturn__)) void* test3(int arg) {
__attribute__((__noreturn__)) void* test3_positive(int arg) {
while (0) foo_test_3();
} // expected-warning{{function declared 'noreturn' should not return}}
+
+
+// PR5298 - -Wmissing-noreturn shouldn't warn if the function is already
+// declared noreturn.
+void __attribute__((noreturn))
+test4() {
+ test2_positive();
+}
diff --git a/test/Sema/return.c b/test/Sema/return.c
index 64def306ebc8..cdd31059b3e7 100644
--- a/test/Sema/return.c
+++ b/test/Sema/return.c
@@ -203,7 +203,11 @@ int test30() {
if (j)
longjmp(test30_j, 1);
else
+#if defined(_WIN32) || defined(_WIN64)
+ longjmp(test30_j, 2);
+#else
_longjmp(test30_j, 1);
+#endif
}
typedef void test31_t(int status);
diff --git a/test/Sema/statements.c b/test/Sema/statements.c
index 9a71a403700d..8eac052a25c7 100644
--- a/test/Sema/statements.c
+++ b/test/Sema/statements.c
@@ -27,3 +27,9 @@ int test8[({10;})]; // expected-error {{statement expression not allowed at file
void test9(const void *P) {
__builtin_prefetch(P);
}
+
+
+void *test10() {
+bar:
+ return &&bar; // expected-warning {{returning address of label, which is local}}
+}
diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c
index 353bbfc25297..e0db63822fb3 100644
--- a/test/Sema/stdcall-fastcall.c
+++ b/test/Sema/stdcall-fastcall.c
@@ -5,6 +5,6 @@ int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' attribute only
int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' attribute only applies to function types}}
// Different CC qualifiers are not compatible
-void __attribute__((stdcall, fastcall)) foo3(); // expected-error{{stdcall and fastcall attributes are not compatible}}
+void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}}
void __attribute__((stdcall)) foo4();
-void __attribute__((fastcall)) foo4(); // expected-error{{fastcall and stdcall attributes are not compatible}}
+void __attribute__((fastcall)) foo4(void); // expected-error{{fastcall and stdcall attributes are not compatible}}
diff --git a/test/Sema/vector-init.c b/test/Sema/vector-init.c
index 18104d871d6c..9dac6c7114da 100644
--- a/test/Sema/vector-init.c
+++ b/test/Sema/vector-init.c
@@ -8,7 +8,7 @@ float4 foo = (float4){ 1.0, 2.0, 3.0, 4.0 };
float4 foo2 = (float4){ 1.0, 2.0, 3.0, 4.0 , 5.0 }; // expected-warning{{excess elements in vector initializer}}
float4 array[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
-int array_sizecheck[(sizeof(array) / sizeof(float4)) == 3? 1 : -1];
+int array_sizecheck[(sizeof(array) / sizeof(float4)) == 3 ? 1 : -1];
float4 array2[2] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
9.0 }; // expected-warning {{excess elements in array initializer}}
@@ -26,5 +26,5 @@ float f1(void) {
// PR5265
typedef float __attribute__((ext_vector_type (3))) float3;
-int test2[(sizeof(float3) == sizeof(float4))*2-1];
+int test2[sizeof(float3) == sizeof(float4) ? 1 : -1];
diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp
index 5ce595cdcece..58d28b55184c 100644
--- a/test/SemaCXX/constructor.cpp
+++ b/test/SemaCXX/constructor.cpp
@@ -14,7 +14,7 @@ class Foo {
static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}}
virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}}
Foo(long) const; // expected-error{{'const' qualifier is not allowed on a constructor}}
-
+
int Foo(int, int); // expected-error{{constructor cannot have a return type}}
};
diff --git a/test/SemaCXX/implicit-int.cpp b/test/SemaCXX/implicit-int.cpp
index 6fa8dd3463d3..723030516dee 100644
--- a/test/SemaCXX/implicit-int.cpp
+++ b/test/SemaCXX/implicit-int.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -fms-extensions=0 %s
x; // expected-error{{C++ requires a type specifier for all declarations}}
diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp
index 90932ed65e31..730beb32698b 100644
--- a/test/SemaCXX/invalid-member-expr.cpp
+++ b/test/SemaCXX/invalid-member-expr.cpp
@@ -5,8 +5,8 @@ class X {};
void test() {
X x;
- x.int; // expected-error{{expected identifier}}
- x.~int(); // expected-error{{expected identifier}}
+ x.int; // expected-error{{expected unqualified-id}}
+ x.~int(); // expected-error{{expected the class name}}
x.operator; // expected-error{{missing type specifier after 'operator'}}
x.operator typedef; // expected-error{{missing type specifier after 'operator'}}
}
@@ -14,8 +14,8 @@ void test() {
void test2() {
X *x;
- x->int; // expected-error{{expected identifier}}
- x->~int(); // expected-error{{expected identifier}}
+ x->int; // expected-error{{expected unqualified-id}}
+ x->~int(); // expected-error{{expected the class name}}
x->operator; // expected-error{{missing type specifier after 'operator'}}
x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
}
diff --git a/test/SemaCXX/invalid-template-specifier.cpp b/test/SemaCXX/invalid-template-specifier.cpp
index a3f081ff60b5..034ad73b086a 100644
--- a/test/SemaCXX/invalid-template-specifier.cpp
+++ b/test/SemaCXX/invalid-template-specifier.cpp
@@ -8,5 +8,5 @@ const template basic_istream<char>; // expected-error {{expected unqualified-id}
namespace S {}
template <class X> class Y {
void x() { S::template y<char>(1); } // expected-error {{does not refer to a template}} \
- // expected-error {{no member named 'y'}}
+ // expected-error {{unqualified-id}}
};
diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp
index 5178557030b7..721758f4cae0 100644
--- a/test/SemaCXX/nested-name-spec.cpp
+++ b/test/SemaCXX/nested-name-spec.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s
+// RUN: clang-cc -fsyntax-only -std=c++98 -verify -fms-extensions=0 %s
namespace A {
struct C {
static int cx;
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index c67a3f653900..6f3e9effe538 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -58,6 +58,7 @@ void bad_news(int *ip)
(void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}}
(void)new int[1][i]; // expected-error {{only the first dimension}}
(void)new (int[1][i]); // expected-error {{only the first dimension}}
+ (void)new (int[i]); // expected-error {{when type is in parentheses}}
(void)new int(*(S*)0); // expected-error {{incompatible type initializing}}
(void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}}
(void)new S(1); // expected-error {{no matching constructor}}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 10b0f5a76804..0f723ad206b9 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -70,6 +70,34 @@ void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2) {
float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type 'bool'}}
}
+// PR5244 - Argument-dependent lookup would include the two operators below,
+// which would break later assumptions and lead to a crash.
+class pr5244_foo
+{
+ pr5244_foo(int);
+ pr5244_foo(char);
+};
+
+bool operator==(const pr5244_foo& s1, const pr5244_foo& s2);
+bool operator==(char c, const pr5244_foo& s);
+
+enum pr5244_bar
+{
+ pr5244_BAR
+};
+
+class pr5244_baz
+{
+ pr5244_bar quux;
+};
+
+void pr5244_barbaz()
+{
+ pr5244_baz quuux;
+ (void)(pr5244_BAR == quuux.quux);
+}
+
+
struct PostInc {
PostInc operator++(int);
diff --git a/test/SemaCXX/ptrtomember-badcall.cpp b/test/SemaCXX/ptrtomember-badcall.cpp
new file mode 100644
index 000000000000..42b8e3b6e0c9
--- /dev/null
+++ b/test/SemaCXX/ptrtomember-badcall.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct S {
+ int i;
+
+ int mem(int);
+};
+
+int foo(int S::* ps, S *s)
+{
+ return (s->*ps)(1); // expected-error {{called object type 'int' is not a function or function pointer}}
+}
+
diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp
index e38f47436d1c..85944a661d41 100644
--- a/test/SemaCXX/typedef-redecl.cpp
+++ b/test/SemaCXX/typedef-redecl.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -fms-extensions=0 %s
typedef int INT;
typedef INT REALLY_INT; // expected-note {{previous definition is here}}
typedef REALLY_INT REALLY_REALLY_INT;
diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp
new file mode 100644
index 000000000000..29d866fa64de
--- /dev/null
+++ b/test/SemaCXX/value-initialization.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct A {
+ const int i; // expected-note {{declared at}}
+ virtual void f() { }
+};
+
+int main () {
+ (void)A(); // expected-error {{cannot define the implicit default constructor for 'struct A', because const member 'i' cannot be default-initialized}}
+}
diff --git a/test/SemaObjC/conditional-expr-6.m b/test/SemaObjC/conditional-expr-6.m
new file mode 100644
index 000000000000..bba51bb8178f
--- /dev/null
+++ b/test/SemaObjC/conditional-expr-6.m
@@ -0,0 +1,51 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+@protocol MyProtocol @end
+
+@interface NSObject @end
+
+@interface NSInterm : NSObject <MyProtocol>
+@end
+
+@interface NSArray : NSInterm
+@end
+
+@interface NSSet : NSObject <MyProtocol>
+@end
+
+
+@interface N1 : NSObject
+@end
+
+@interface N1() <MyProtocol>
+@end
+
+NSObject* test (int argc) {
+ NSArray *array = ((void*)0);
+ NSSet *set = ((void*)0);
+ return (argc) ? set : array ;
+}
+
+
+NSObject* test1 (int argc) {
+ NSArray *array = ((void*)0);
+ NSSet *set = ((void*)0);
+ id <MyProtocol> instance = (argc) ? array : set;
+ id <MyProtocol> instance1 = (argc) ? set : array;
+
+ N1 *n1 = ((void*)0);
+ id <MyProtocol> instance2 = (argc) ? set : n1;
+ id <MyProtocol> instance3 = (argc) ? n1 : array;
+
+ NSArray<MyProtocol> *qual_array = ((void*)0);
+ id <MyProtocol> instance4 = (argc) ? array : qual_array;
+ id <MyProtocol> instance5 = (argc) ? qual_array : array;
+ NSSet<MyProtocol> *qual_set = ((void*)0);
+ id <MyProtocol> instance6 = (argc) ? qual_set : qual_array;
+ id <MyProtocol> instance7 = (argc) ? qual_set : array;
+ id <MyProtocol> instance8 = (argc) ? qual_array : set;
+ id <MyProtocol> instance9 = (argc) ? qual_array : qual_set;
+
+
+ return (argc) ? array : set;
+}
diff --git a/test/SemaObjC/continuation-class-err.m b/test/SemaObjC/continuation-class-err.m
index f516a9326a95..262b786b5408 100644
--- a/test/SemaObjC/continuation-class-err.m
+++ b/test/SemaObjC/continuation-class-err.m
@@ -5,11 +5,36 @@
id _object;
id _object1;
}
-@property(readonly) id object;
-@property(readwrite, assign) id object1;
+@property(readonly) id object; // expected-note {{property declared here}}
+@property(readwrite, assign) id object1; // expected-note {{property declared here}}
@end
@interface ReadOnly ()
-@property(readwrite, copy) id object;
-@property(readonly) id object1; // expected-error {{attribute of property in continuation class of 'ReadOnly' can only be 'readwrite'}}
+@property(readwrite, copy) id object; // expected-warning {{property attribute in continuation class does not match the primary class}}
+@property(readonly) id object1; // expected-error {{property declaration in continuation class of 'ReadOnly' is to change a 'readonly' property to 'readwrite'}}
@end
+
+@protocol Proto
+ @property (copy) id fee; // expected-note {{property declared here}}
+@end
+
+@protocol Foo<Proto>
+ @property (copy) id foo; // expected-note {{property declared here}}
+@end
+
+@interface Bar <Foo> {
+ id _foo;
+ id _fee;
+}
+@end
+
+@interface Bar ()
+@property (copy) id foo; // expected-error {{property declaration in continuation class of 'Bar' is to change a 'readonly' property to 'readwrite'}}
+@property (copy) id fee; // expected-error {{property declaration in continuation class of 'Bar' is to change a 'readonly' property to 'readwrite'}}
+@end
+
+@implementation Bar
+@synthesize foo = _foo;
+@synthesize fee = _fee;
+@end
+
diff --git a/test/SemaObjC/id-isa-ref.m b/test/SemaObjC/id-isa-ref.m
index dc42f9a53965..fa3293ce79b5 100644
--- a/test/SemaObjC/id-isa-ref.m
+++ b/test/SemaObjC/id-isa-ref.m
@@ -1,7 +1,7 @@
// RUN: clang-cc -fsyntax-only -verify %s
// Failing currently due to Obj-C type representation changes. 2009-09-17
-// XFAIL
+// XFAIL: *
typedef struct objc_object {
struct objc_class *isa;
diff --git a/test/SemaObjC/property-category-4.m b/test/SemaObjC/property-category-4.m
new file mode 100644
index 000000000000..ee08b09c0137
--- /dev/null
+++ b/test/SemaObjC/property-category-4.m
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+@interface IDELogNavigator
+{
+ id selectedObjects;
+}
+@end
+
+@interface IDELogNavigator (CAT)
+ @property (readwrite, retain) id selectedObjects; // expected-note {{property declared here}}
+ @property (readwrite, retain) id d_selectedObjects; // expected-note {{property declared here}}
+@end
+
+@implementation IDELogNavigator
+@synthesize selectedObjects = _selectedObjects; // expected-error {{property declared in category 'CAT' cannot be implemented in class implementation}}
+@dynamic d_selectedObjects; // expected-error {{property declared in category 'CAT' cannot be implemented in class implementation}}
+@end
+
diff --git a/test/SemaObjC/return.m b/test/SemaObjC/return.m
index 9acf47079958..ff6499479458 100644
--- a/test/SemaObjC/return.m
+++ b/test/SemaObjC/return.m
@@ -1,6 +1,22 @@
-// RUN: clang-cc %s -fsyntax-only -verify
+// RUN: clang-cc %s -fsyntax-only -verify -Wmissing-noreturn
int test1() {
id a;
@throw a;
}
+
+// PR5286
+void test2(int a) {
+ while (1) {
+ if (a)
+ return;
+ }
+}
+
+// PR5286
+void test3(int a) { // expected-warning {{function could be attribute 'noreturn'}}
+ while (1) {
+ if (a)
+ @throw (id)0;
+ }
+}
diff --git a/test/SemaObjCXX/overload.mm b/test/SemaObjCXX/overload.mm
index 47141002864c..56dc5108eb95 100644
--- a/test/SemaObjCXX/overload.mm
+++ b/test/SemaObjCXX/overload.mm
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// XFAIL: *
@interface Foo
@end
diff --git a/test/SemaObjCXX/references.mm b/test/SemaObjCXX/references.mm
index 82797cef77c7..e02f360f7876 100644
--- a/test/SemaObjCXX/references.mm
+++ b/test/SemaObjCXX/references.mm
@@ -1,7 +1,7 @@
// FIXME: This crashes, disable it until fixed.
// RN: clang-cc -verify -emit-llvm -o - %s
// RUN: false
-// XFAIL
+// XFAIL: *
// Test reference binding.
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index e44115c748c3..4cd43b469ae0 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -20,8 +20,7 @@ int test_incomplete_specs(A<double, double> *a1,
A<double> *a2)
{
(void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
- (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} \
- // expected-note{{first required here}}
+ (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
}
typedef float FLOAT;
@@ -71,8 +70,7 @@ namespace N {
}
// Diagnose specialization errors
-struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} \
- // expected-error{{after instantiation}}
+struct A<double> { }; // expected-error{{template specialization requires 'template<>'}}
template<> struct ::A<double>;
@@ -100,3 +98,9 @@ template<> struct N::B<char> {
int testf(int x) { return f(x); }
};
+// PR5264
+template <typename T> class Foo;
+Foo<int>* v;
+Foo<int>& F() { return *v; }
+template <typename T> class Foo {};
+Foo<int> x;
diff --git a/test/SemaTemplate/constructor-template.cpp b/test/SemaTemplate/constructor-template.cpp
index acd845bc2fd5..79bf7c585e34 100644
--- a/test/SemaTemplate/constructor-template.cpp
+++ b/test/SemaTemplate/constructor-template.cpp
@@ -51,3 +51,4 @@ void test_X1(X1<int> xi) {
template<class C> struct A {};
template <> struct A<int>{A(const A<int>&);};
struct B { A<int> x; B(B& a) : x(a.x) {} };
+
diff --git a/test/SemaTemplate/copy-ctor-assign.cpp b/test/SemaTemplate/copy-ctor-assign.cpp
index 90fb0133a721..69481ea557f4 100644
--- a/test/SemaTemplate/copy-ctor-assign.cpp
+++ b/test/SemaTemplate/copy-ctor-assign.cpp
@@ -33,4 +33,20 @@ void test3(X<int> &x, X<int> xi, X<long> xl, X<int Y::*> xmptr) {
x = xi;
x = xl;
x = xmptr; // expected-note{{instantiation}}
-} \ No newline at end of file
+}
+
+struct X1 {
+ X1 &operator=(const X1&);
+};
+
+template<typename T>
+struct X2 : X1 {
+ template<typename U> X2 &operator=(const U&);
+};
+
+struct X3 : X2<int> {
+};
+
+void test_X2(X3 &to, X3 from) {
+ to = from;
+}
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
index 575283ed8b51..9c0f1ecf0c3b 100644
--- a/test/SemaTemplate/default-expr-arguments.cpp
+++ b/test/SemaTemplate/default-expr-arguments.cpp
@@ -84,3 +84,27 @@ struct X1 {
void test_X1() {
X1<int> x1;
}
+
+// PR5283
+namespace PR5283 {
+template<typename T> struct A {
+ A(T = 1); // expected-error 3 {{incompatible type initializing 'int', expected 'int *'}}
+};
+
+struct B : A<int*> {
+ B();
+};
+B::B() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
+
+struct C : virtual A<int*> {
+ C();
+};
+C::C() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
+
+struct D {
+ D();
+
+ A<int*> a;
+};
+D::D() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
+}
diff --git a/test/SemaTemplate/ext-vector-type.cpp b/test/SemaTemplate/ext-vector-type.cpp
index b6aebc102fb4..7cc4ae930ed2 100644
--- a/test/SemaTemplate/ext-vector-type.cpp
+++ b/test/SemaTemplate/ext-vector-type.cpp
@@ -45,3 +45,16 @@ struct make5 {
typedef int_ptr __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type}}
};
+template<int Length>
+struct make6 {
+ typedef int __attribute__((ext_vector_type(Length))) type;
+};
+
+int test_make6() {
+ make6<4>::type x;
+ x.w = 7;
+
+ make6<2>::type y;
+ y.x = -1;
+ y.w = -1; // expected-error{{vector component access exceeds type}}
+}
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index 761c13076d2a..84a8e899dbea 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -54,6 +54,7 @@ struct X1 {
template<typename U> void f2(U);
X1<int> x1i;
+X0<int*> x0ip;
template<> void f2(int);
@@ -62,3 +63,31 @@ template<> void f2(int);
template<typename U> void f3(U);
template<> void f3(int);
+
+// PR5332
+template <typename T>
+class Foo {
+ template <typename U>
+ friend class Foo;
+};
+
+Foo<int> foo;
+
+template<typename T, T Value>
+struct X2a;
+
+template<typename T, int Size>
+struct X2b;
+
+template<typename T>
+class X3 {
+ template<typename U, U Value>
+ friend struct X2a;
+
+ template<typename U, T Value>
+ friend struct X2b;
+};
+
+X3<int> x3i; // okay
+
+X3<long> x3l; // FIXME: should cause an instantiation-time failure
diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp
index 6b3fc6e12534..c3c318f36d5d 100644
--- a/test/SemaTemplate/instantiate-cast.cpp
+++ b/test/SemaTemplate/instantiate-cast.cpp
@@ -96,7 +96,6 @@ struct FunctionalCast1 {
template struct FunctionalCast1<int, float>;
template struct FunctionalCast1<A, int>; // expected-note{{instantiation}}
-#if 0
// Generates temporaries, which we cannot handle yet.
template<int N, long M>
struct FunctionalCast2 {
@@ -106,4 +105,13 @@ struct FunctionalCast2 {
};
template struct FunctionalCast2<1, 3>;
-#endif
+
+// ---------------------------------------------------------------------
+// implicit casting
+// ---------------------------------------------------------------------
+template<typename T>
+struct Derived2 : public Base { };
+
+void test_derived_to_base(Base *&bp, Derived2<int> *dp) {
+ bp = dp;
+}
diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp
index 21ee87202797..ab12b90f6c98 100644
--- a/test/SemaTemplate/instantiate-declref-ice.cpp
+++ b/test/SemaTemplate/instantiate-declref-ice.cpp
@@ -5,3 +5,33 @@ template<int i> struct x {
x<j>* y;
};
+template<int i>
+const int x<i>::j;
+
+int array0[x<2>::j];
+
+
+template<typename T>
+struct X0 {
+ static const unsigned value = sizeof(T);
+};
+
+template<typename T>
+const unsigned X0<T>::value;
+
+int array1[X0<int>::value == sizeof(int)? 1 : -1];
+
+const unsigned& testX0() { return X0<int>::value; }
+
+int array2[X0<int>::value == sizeof(int)? 1 : -1];
+
+template<typename T>
+struct X1 {
+ static const unsigned value;
+};
+
+template<typename T>
+const unsigned X1<T>::value = sizeof(T);
+
+int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length arrays are not permitted in C++}} \
+// expected-error{{variable length array declaration not allowed at file scope}}
diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp
index 051c6050abea..359e2c7dfaa4 100644
--- a/test/SemaTemplate/instantiate-declref.cpp
+++ b/test/SemaTemplate/instantiate-declref.cpp
@@ -69,3 +69,21 @@ namespace N2 {
template struct N2::Outer2::Inner<float>;
template struct N2::Outer2::Inner<int*, float*>; // expected-note{{instantiation}}
+
+// Test dependent pointer-to-member expressions.
+template<typename T>
+struct smart_ptr {
+ struct safe_bool {
+ int member;
+ };
+
+ operator int safe_bool::*() const {
+ return ptr? &safe_bool::member : 0;
+ }
+
+ T* ptr;
+};
+
+void test_smart_ptr(smart_ptr<int> p) {
+ if (p) { }
+}
diff --git a/test/SemaTemplate/instantiate-function-1.mm b/test/SemaTemplate/instantiate-function-1.mm
index be995e7ff615..c119ab5da8b9 100644
--- a/test/SemaTemplate/instantiate-function-1.mm
+++ b/test/SemaTemplate/instantiate-function-1.mm
@@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
+// XFAIL: *
template<typename T> struct Member0 {
void f(T t) {
diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp
index f7c09ef87900..df1e1d964eb6 100644
--- a/test/SemaTemplate/instantiate-method.cpp
+++ b/test/SemaTemplate/instantiate-method.cpp
@@ -81,3 +81,20 @@ int *a(A0<int> &x0, A1<int> &x1) {
int *y0 = x0;
int *y1 = x1; // expected-error{{initializing}}
}
+
+struct X0Base {
+ int &f();
+};
+
+template<typename T>
+struct X0 : X0Base {
+};
+
+template<typename U>
+struct X1 : X0<U> {
+ int &f2() { return X0Base::f(); }
+};
+
+void test_X1(X1<int> x1i) {
+ int &ir = x1i.f2();
+}
diff --git a/test/SemaTemplate/instantiate-non-type-template-parameter.cpp b/test/SemaTemplate/instantiate-non-type-template-parameter.cpp
new file mode 100644
index 000000000000..32acbd0d8bdc
--- /dev/null
+++ b/test/SemaTemplate/instantiate-non-type-template-parameter.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5311
+template<typename T>
+class StringSwitch {
+public:
+ template<unsigned N>
+ void Case(const char (&S)[N], const int & Value) {
+ }
+};
+
+int main(int argc, char *argv[]) {
+ (void)StringSwitch<int>();
+}
diff --git a/test/SemaTemplate/instantiate-subscript.cpp b/test/SemaTemplate/instantiate-subscript.cpp
index 434d84e2b893..20e2c39d0cce 100644
--- a/test/SemaTemplate/instantiate-subscript.cpp
+++ b/test/SemaTemplate/instantiate-subscript.cpp
@@ -6,7 +6,7 @@ struct Sub0 {
};
struct Sub1 {
- long &operator[](long);
+ long &operator[](long); // expected-note{{candidate function}}
};
struct ConvertibleToInt {
@@ -24,3 +24,18 @@ template struct Subscript0<int*, int, int&>;
template struct Subscript0<Sub0, int, int&>;
template struct Subscript0<Sub1, ConvertibleToInt, long&>;
template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}}
+
+// PR5345
+template <typename T>
+struct S {
+ bool operator[](int n) const { return true; }
+};
+
+template <typename T>
+void Foo(const S<int>& s, T x) {
+ if (s[0]) {}
+}
+
+void Bar() {
+ Foo(S<int>(), 0);
+}
diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp
index 0f9f21f339d1..0238cd53c553 100644
--- a/test/SemaTemplate/member-template-access-expr.cpp
+++ b/test/SemaTemplate/member-template-access-expr.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
template<typename U, typename T>
U f0(T t) {
return t.template get<U>();
@@ -50,3 +49,47 @@ B<T>::destroy()
void do_destroy_B(B<int> b) {
b.destroy();
}
+
+struct X1 {
+ int* f1(int);
+ template<typename T> float* f1(T);
+
+ static int* f2(int);
+ template<typename T> static float* f2(T);
+};
+
+void test_X1(X1 x1) {
+ float *fp1 = x1.f1<>(17);
+ float *fp2 = x1.f1<int>(3.14);
+ int *ip1 = x1.f1(17);
+ float *ip2 = x1.f1(3.14);
+
+ float* (X1::*mf1)(int) = &X1::f1;
+ float* (X1::*mf2)(int) = &X1::f1<>;
+ float* (X1::*mf3)(float) = &X1::f1<float>;
+
+ float* (*fp3)(int) = &X1::f2;
+ float* (*fp4)(int) = &X1::f2<>;
+ float* (*fp5)(float) = &X1::f2<float>;
+ float* (*fp6)(int) = X1::f2;
+ float* (*fp7)(int) = X1::f2<>;
+ float* (*fp8)(float) = X1::f2<float>;
+}
+
+template<int A> struct X2 {
+ int m;
+};
+
+template<typename T>
+struct X3 : T { };
+
+template<typename T>
+struct X4 {
+ template<typename U>
+ void f(X2<sizeof(X3<U>().U::m)>);
+};
+
+void f(X4<X3<int> > x4i) {
+ X2<sizeof(int)> x2;
+ x4i.f<X2<sizeof(int)> >(x2);
+}
diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp
index a5aa2dcb527a..1bdc7a89d4e8 100644
--- a/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/test/SemaTemplate/nested-name-spec-template.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -fms-extensions=0 %s
namespace N {
namespace M {
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
index 5ee2c9954005..4d948184cee9 100644
--- a/test/SemaTemplate/nested-template.cpp
+++ b/test/SemaTemplate/nested-template.cpp
@@ -101,3 +101,10 @@ struct X0<T*> {
template<typename U>
void f(U u = T()) { }
};
+
+// PR5103
+template<typename>
+struct X1 {
+ template<typename, bool = false> struct B { };
+};
+template struct X1<int>::B<bool>;
diff --git a/test/SemaTemplate/operator-function-id-template.cpp b/test/SemaTemplate/operator-function-id-template.cpp
new file mode 100644
index 000000000000..92a8c84e3be6
--- /dev/null
+++ b/test/SemaTemplate/operator-function-id-template.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct A {
+ template<typename U> A<T> operator+(U);
+};
+
+template<int Value, typename T> bool operator==(A<T>, A<T>);
+
+template<> bool operator==<0>(A<int>, A<int>);
+
+bool test_qualified_id(A<int> ai) {
+ return ::operator==<0, int>(ai, ai);
+}
+
+void test_op(A<int> a, int i) {
+ const A<int> &air = a.operator+<int>(i);
+}
+
+template<typename T>
+void test_op_template(A<T> at, T x) {
+ const A<T> &atr = at.template operator+<T>(x);
+ const A<T> &atr2 = at.A::template operator+<T>(x);
+ // FIXME: unrelated template-name instantiation issue
+ // const A<T> &atr3 = at.template A<T>::template operator+<T>(x);
+}
+
+template void test_op_template<float>(A<float>, float);
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
new file mode 100644
index 000000000000..a0cbe4408494
--- /dev/null
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5336
+template<typename FromCl>
+struct isa_impl_cl {
+ template<class ToCl>
+ static void isa(const FromCl &Val) { }
+};
+
+template<class X, class Y>
+void isa(const Y &Val) { return isa_impl_cl<Y>::template isa<X>(Val); }
+
+class Value;
+void f0(const Value &Val) { isa<Value>(Val); }
diff --git a/test/SemaTemplate/template-id-printing.cpp b/test/SemaTemplate/template-id-printing.cpp
new file mode 100644
index 000000000000..13250943e92c
--- /dev/null
+++ b/test/SemaTemplate/template-id-printing.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -ast-print %s | FileCheck %s
+namespace N {
+ template<typename T, typename U> void f(U);
+ template<int> void f();
+}
+
+void g() {
+ // CHECK: N::f<int>(3.14
+ N::f<int>(3.14);
+
+ // CHECK: N::f<double>
+ void (*fp)(int) = N::f<double>;
+}
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 9dabafcde1f4..c88c90b7c5df 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -5,6 +5,7 @@ config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
config.clang_obj_root = "@CLANG_BINARY_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
# Let the main config do the real work.
lit.load_config(config, "@CLANG_SOURCE_DIR@/test/lit.cfg")
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 64dfcfea5143..4798e2832822 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -116,6 +116,10 @@ class TUVisitor : public DeclVisitor<TUVisitor> {
if (ND->getPCHLevel() > MaxPCHLevel)
return;
+ // Filter any implicit declarations (since the source info will be bogus).
+ if (ND->isImplicit())
+ return;
+
CXCursor C = { CK, ND, 0 };
Callback(TUnit, C, CData);
}
@@ -380,10 +384,8 @@ CXTranslationUnit clang_createTranslationUnit(
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true);
- if (!ErrMsg.empty()) {
- (llvm::errs() << "clang_createTranslationUnit: " << ErrMsg
- << '\n').flush();
- }
+ if (!ErrMsg.empty())
+ llvm::errs() << "clang_createTranslationUnit: " << ErrMsg << '\n';
return TU;
}
@@ -436,8 +438,9 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
// Add the null terminator.
argv.push_back(NULL);
-#ifndef LLVM_ON_WIN32
- llvm::sys::Path DevNull("/dev/null");
+ // Invoke 'clang'.
+ llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
+ // on Unix or NUL (Windows).
std::string ErrMsg;
const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DevNull, NULL };
llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
@@ -448,16 +451,12 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
llvm::errs() << "clang_createTranslationUnitFromSourceFile: " << ErrMsg
<< '\n' << "Arguments: \n";
for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
- I!=E; ++I)
- if (*I) llvm::errs() << ' ' << *I << '\n';
-
- (llvm::errs() << '\n').flush();
+ I!=E; ++I) {
+ if (*I)
+ llvm::errs() << ' ' << *I << '\n';
+ }
+ llvm::errs() << '\n';
}
-#else
- // FIXME: I don't know what is the equivalent '/dev/null' redirect for
- // Windows for this API.
- llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0]);
-#endif
// Finally, we create the translation unit from the ast file.
ASTUnit *ATU = static_cast<ASTUnit *>(
@@ -550,7 +549,13 @@ const char *clang_getDeclSpelling(CXDecl AnonDecl)
if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
return OMD->getSelector().getAsString().c_str();
- }
+ }
+ if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+ // No, this isn't the same as the code below. getIdentifier() is non-virtual
+ // and returns different names. NamedDecl returns the class name and
+ // ObjCCategoryImplDecl returns the category name.
+ return CIMP->getIdentifier()->getNameStart();
+
if (ND->getIdentifier())
return ND->getIdentifier()->getNameStart();
else
@@ -576,9 +581,40 @@ unsigned clang_getDeclColumn(CXDecl AnonDecl)
const char *clang_getDeclSource(CXDecl AnonDecl)
{
assert(AnonDecl && "Passed null CXDecl");
+ FileEntry *FEnt = static_cast<FileEntry *>(clang_getDeclSourceFile(AnonDecl));
+ assert (FEnt && "Cannot find FileEntry for Decl");
+ return clang_getFileName(FEnt);
+}
+
+static const FileEntry *getFileEntryFromSourceLocation(SourceManager &SMgr,
+ SourceLocation SLoc)
+{
+ FileID FID;
+ if (SLoc.isFileID())
+ FID = SMgr.getFileID(SLoc);
+ else
+ FID = SMgr.getDecomposedSpellingLoc(SLoc).first;
+ return SMgr.getFileEntryForID(FID);
+}
+
+CXFile clang_getDeclSourceFile(CXDecl AnonDecl)
+{
+ assert(AnonDecl && "Passed null CXDecl");
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return SourceMgr.getBufferName(ND->getLocation());
+ return (void *)getFileEntryFromSourceLocation(SourceMgr, ND->getLocation());
+}
+
+const char *clang_getFileName(CXFile SFile) {
+ assert(SFile && "Passed null CXFile");
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return FEnt->getName();
+}
+
+time_t clang_getFileTime(CXFile SFile) {
+ assert(SFile && "Passed null CXFile");
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return FEnt->getModificationTime();
}
const char *clang_getCursorSpelling(CXCursor C)
@@ -695,26 +731,12 @@ static enum CXCursorKind TranslateKind(Decl *D) {
//
// CXCursor Operations.
//
-void clang_initCXLookupHint(CXLookupHint *hint) {
- memset(hint, 0, sizeof(*hint));
-}
-
CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
- unsigned line, unsigned column) {
- return clang_getCursorWithHint(CTUnit, source_name, line, column, NULL);
-}
-
-CXCursor clang_getCursorWithHint(CXTranslationUnit CTUnit,
- const char *source_name,
- unsigned line, unsigned column,
- CXLookupHint *hint)
+ unsigned line, unsigned column)
{
assert(CTUnit && "Passed null CXTranslationUnit");
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- // FIXME: Make this better.
- CXDecl RelativeToDecl = hint ? hint->decl : NULL;
-
FileManager &FMgr = CXXUnit->getFileManager();
const FileEntry *File = FMgr.getFile(source_name,
source_name+strlen(source_name));
@@ -725,9 +747,13 @@ CXCursor clang_getCursorWithHint(CXTranslationUnit CTUnit,
SourceLocation SLoc =
CXXUnit->getSourceManager().getLocation(File, line, column);
- ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
- static_cast<NamedDecl *>(RelativeToDecl));
-
+ ASTLocation LastLoc = CXXUnit->getLastASTLocation();
+
+ ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
+ &LastLoc);
+ if (ALoc.isValid())
+ CXXUnit->setLastASTLocation(ALoc);
+
Decl *Dcl = ALoc.getParentDecl();
if (ALoc.isNamedRef())
Dcl = ALoc.AsNamedRef().ND;
@@ -935,6 +961,16 @@ const char *clang_getCursorSource(CXCursor C)
return Buffer->getBufferIdentifier();
}
+CXFile clang_getCursorSourceFile(CXCursor C)
+{
+ assert(C.decl && "CXCursor has null decl");
+ NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
+ SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+
+ return (void *)getFileEntryFromSourceLocation(SourceMgr,
+ getLocationFromCursor(C,SourceMgr, ND));
+}
+
void clang_getDefinitionSpellingAndExtent(CXCursor C,
const char **startBuf,
const char **endBuf,
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index e9d44a0dc918..5f461d8ef600 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -1,32 +1,34 @@
_clang_createIndex
+_clang_createTranslationUnit
+_clang_createTranslationUnitFromSourceFile
_clang_disposeIndex
+_clang_disposeTranslationUnit
_clang_getCursor
_clang_getCursorColumn
_clang_getCursorDecl
_clang_getCursorFromDecl
_clang_getCursorKind
+_clang_getCursorKindSpelling
_clang_getCursorLine
_clang_getCursorSource
-_clang_getCursorWithHint
-_clang_getDeclarationName
-_clang_getDeclSpelling
-_clang_getDeclLine
+_clang_getCursorSourceFile
+_clang_getCursorSpelling
_clang_getDeclColumn
+_clang_getDeclLine
_clang_getDeclSource
+_clang_getDeclSourceFile
+_clang_getDeclSpelling
+_clang_getDeclarationName
+_clang_getDefinitionSpellingAndExtent
_clang_getEntity
_clang_getEntityFromDecl
+_clang_getFileName
+_clang_getFileTime
+_clang_getTranslationUnitSpelling
_clang_getURI
-_clang_loadDeclaration
-_clang_loadTranslationUnit
-_clang_createTranslationUnit
-_clang_createTranslationUnitFromSourceFile
-_clang_disposeTranslationUnit
-_clang_initCXLookupHint
_clang_isDeclaration
-_clang_isReference
_clang_isDefinition
_clang_isInvalid
-_clang_getCursorSpelling
-_clang_getCursorKindSpelling
-_clang_getDefinitionSpellingAndExtent
-_clang_getTranslationUnitSpelling
+_clang_isReference
+_clang_loadDeclaration
+_clang_loadTranslationUnit
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index ee77c0398f72..dd0eeea9443a 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -26,6 +26,7 @@ if(MSVC)
# windows.h doesn't compile with /Za
get_target_property(NON_ANSI_COMPILE_FLAGS CIndex COMPILE_FLAGS)
string(REPLACE /Za "" NON_ANSI_COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ set(NON_ANSI_COMPILE_FLAGS "${NON_ANSI_COMPILE_FLAGS} /D_CINDEX_LIB_")
set_target_properties(CIndex PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
endif(MSVC)
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index cb2aa2004ce7..222512af1546 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -6,7 +6,4 @@ if (CLANG_BUILD_EXPERIMENTAL)
add_subdirectory(wpa)
endif ()
add_subdirectory(CIndex)
-if (MSVC)
-else ()
- add_subdirectory(c-index-test)
-endif ()
+add_subdirectory(c-index-test)
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index cf2a706891e3..8791ee20a583 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -4,7 +4,23 @@
#include <stdio.h>
#include <string.h>
+#ifdef _MSC_VER
+char *basename(const char* path)
+{
+ char* base1 = (char*)strrchr(path, '/');
+ char* base2 = (char*)strrchr(path, '\\');
+ if (base1 && base2)
+ return((base1 > base2) ? base1 + 1 : base2 + 1);
+ else if (base1)
+ return(base1 + 1);
+ else if (base2)
+ return(base2 + 1);
+
+ return((char*)path);
+}
+#else
extern char *basename(const char *);
+#endif
static void PrintCursor(CXCursor Cursor) {
if (clang_isInvalid(Cursor.kind))
@@ -54,7 +70,6 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
CXCursor Ref;
while (startBuf < endBuf) {
- CXLookupHint hint;
if (*startBuf == '\n') {
startBuf++;
curLine++;
@@ -62,11 +77,8 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,
} else if (*startBuf != '\t')
curColumn++;
- clang_initCXLookupHint(&hint);
- hint.decl = Cursor.decl;
-
- Ref = clang_getCursorWithHint(Unit, clang_getCursorSource(Cursor),
- curLine, curColumn, &hint);
+ Ref = clang_getCursor(Unit, clang_getCursorSource(Cursor),
+ curLine, curColumn);
if (Ref.kind == CXCursor_NoDeclFound) {
/* Nothing found here; that's fine. */
} else if (Ref.kind != CXCursor_FunctionDecl) {
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index f77767c150e9..671fc35d182b 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -26,6 +26,7 @@
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompileOptions.h"
+#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FixItRewriter.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/InitHeaderSearch.h"
@@ -69,7 +70,6 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
-#include "llvm/System/Process.h"
#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
@@ -106,8 +106,6 @@ static bool ResolveParsedLocation(ParsedSourceLocation &ParsedLoc,
/// anything.
llvm::Timer *ClangFrontendTimer = 0;
-static bool HadErrors = false;
-
static llvm::cl::opt<bool>
Verbose("v", llvm::cl::desc("Enable verbose output"));
static llvm::cl::opt<bool>
@@ -240,6 +238,8 @@ TokenCache("token-cache", llvm::cl::value_desc("path"),
// Diagnostic Options
//===----------------------------------------------------------------------===//
+static DiagnosticOptions DiagOpts;
+
static llvm::cl::opt<bool>
VerifyDiagnostics("verify",
llvm::cl::desc("Verify emitted diagnostics and warnings"));
@@ -283,10 +283,9 @@ MessageLength("fmessage-length",
llvm::cl::value_desc("N"));
static llvm::cl::opt<bool>
-NoColorDiagnostic("fno-color-diagnostics",
- llvm::cl::desc("Don't use colors when showing diagnostics "
- "(automatically turned off if output is not a "
- "terminal)."));
+PrintColorDiagnostic("fcolor-diagnostics",
+ llvm::cl::desc("Use colors in diagnostics"));
+
//===----------------------------------------------------------------------===//
// C++ Visualization.
//===----------------------------------------------------------------------===//
@@ -655,10 +654,18 @@ static llvm::cl::opt<bool>
NoElideConstructors("fno-elide-constructors",
llvm::cl::desc("Disable C++ copy constructor elision"));
+static llvm::cl::opt<bool>
+NoMergeConstants("fno-merge-all-constants",
+ llvm::cl::desc("Disallow merging of constants."));
+
static llvm::cl::opt<std::string>
TargetABI("target-abi",
llvm::cl::desc("Target a particular ABI type"));
+static llvm::cl::opt<std::string>
+TargetTriple("triple",
+ llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
+
// It might be nice to add bounds to the CommandLine library directly.
struct OptLevelParser : public llvm::cl::parser<unsigned> {
@@ -878,132 +885,6 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
}
//===----------------------------------------------------------------------===//
-// Target Triple Processing.
-//===----------------------------------------------------------------------===//
-
-static llvm::cl::opt<std::string>
-TargetTriple("triple",
- llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)"));
-
-static llvm::cl::opt<std::string>
-MacOSVersionMin("mmacosx-version-min",
- llvm::cl::desc("Specify target Mac OS X version (e.g. 10.5)"));
-
-// If -mmacosx-version-min=10.3.9 is specified, change the triple from being
-// something like powerpc-apple-darwin9 to powerpc-apple-darwin7
-
-// FIXME: We should have the driver do this instead.
-static void HandleMacOSVersionMin(llvm::Triple &Triple) {
- if (Triple.getOS() != llvm::Triple::Darwin) {
- fprintf(stderr,
- "-mmacosx-version-min only valid for darwin (Mac OS X) targets\n");
- exit(1);
- }
-
- // Validate that MacOSVersionMin is a 'version number', starting with 10.[3-9]
- if (MacOSVersionMin.size() < 4 ||
- MacOSVersionMin.substr(0, 3) != "10." ||
- !isdigit(MacOSVersionMin[3])) {
- fprintf(stderr,
- "-mmacosx-version-min=%s is invalid, expected something like '10.4'.\n",
- MacOSVersionMin.c_str());
- exit(1);
- }
-
- unsigned VersionNum = MacOSVersionMin[3]-'0';
-
- if (VersionNum <= 4 && Triple.getArch() == llvm::Triple::x86_64) {
- fprintf(stderr,
- "-mmacosx-version-min=%s is invalid with -arch x86_64.\n",
- MacOSVersionMin.c_str());
- exit(1);
- }
-
-
- llvm::SmallString<16> NewDarwinString;
- NewDarwinString += "darwin";
-
- // Turn MacOSVersionMin into a darwin number: e.g. 10.3.9 is 3 -> darwin7.
- VersionNum += 4;
- if (VersionNum > 9) {
- NewDarwinString += '1';
- VersionNum -= 10;
- }
- NewDarwinString += (VersionNum+'0');
-
- if (MacOSVersionMin.size() == 4) {
- // "10.4" is ok.
- } else if (MacOSVersionMin.size() == 6 &&
- MacOSVersionMin[4] == '.' &&
- isdigit(MacOSVersionMin[5])) { // 10.4.7 is ok.
- // Add the period piece (.7) to the end of the triple. This gives us
- // something like ...-darwin8.7
- NewDarwinString += '.';
- NewDarwinString += MacOSVersionMin[5];
- } else { // "10.4" is ok. 10.4x is not.
- fprintf(stderr,
- "-mmacosx-version-min=%s is invalid, expected something like '10.4'.\n",
- MacOSVersionMin.c_str());
- exit(1);
- }
-
- Triple.setOSName(NewDarwinString.str());
-}
-
-static llvm::cl::opt<std::string>
-IPhoneOSVersionMin("miphoneos-version-min",
- llvm::cl::desc("Specify target iPhone OS version (e.g. 2.0)"));
-
-// If -miphoneos-version-min=2.2 is specified, change the triple from being
-// something like armv6-apple-darwin10 to armv6-apple-darwin9.2.2. We use
-// 9 as the default major Darwin number, and encode the iPhone OS version
-// number in the minor version and revision.
-
-// FIXME: We should have the driver do this instead.
-static void HandleIPhoneOSVersionMin(llvm::Triple &Triple) {
- if (Triple.getOS() != llvm::Triple::Darwin) {
- fprintf(stderr,
- "-miphoneos-version-min only valid for darwin (Mac OS X) targets\n");
- exit(1);
- }
-
- // Validate that IPhoneOSVersionMin is a 'version number', starting with
- // [2-9].[0-9]
- if (IPhoneOSVersionMin.size() != 3 || !isdigit(IPhoneOSVersionMin[0]) ||
- IPhoneOSVersionMin[1] != '.' || !isdigit(IPhoneOSVersionMin[2])) {
- fprintf(stderr,
- "-miphoneos-version-min=%s is invalid, expected something like '2.0'.\n",
- IPhoneOSVersionMin.c_str());
- exit(1);
- }
-
- // Turn IPhoneOSVersionMin into a darwin number: e.g. 2.0 is 2 -> 9.2.0
- llvm::SmallString<16> NewDarwinString;
- NewDarwinString += "darwin9.";
- NewDarwinString += IPhoneOSVersionMin;
- Triple.setOSName(NewDarwinString.str());
-}
-
-/// CreateTargetTriple - Process the various options that affect the target
-/// triple and build a final aggregate triple that we are compiling for.
-static llvm::Triple CreateTargetTriple() {
- // Initialize base triple. If a -triple option has been specified, use
- // that triple. Otherwise, default to the host triple.
- llvm::Triple Triple(TargetTriple);
- if (Triple.getTriple().empty())
- Triple = llvm::Triple(llvm::sys::getHostTriple());
-
- // If -mmacosx-version-min=10.3.9 is specified, change the triple from being
- // something like powerpc-apple-darwin9 to powerpc-apple-darwin7
- if (!MacOSVersionMin.empty())
- HandleMacOSVersionMin(Triple);
- else if (!IPhoneOSVersionMin.empty())
- HandleIPhoneOSVersionMin(Triple);
-
- return Triple;
-}
-
-//===----------------------------------------------------------------------===//
// SourceManager initialization.
//===----------------------------------------------------------------------===//
@@ -1056,6 +937,9 @@ static bool InitializeSourceManager(Preprocessor &PP,
// -A... - Play with #assertions
// -undef - Undefine all predefined macros
+static llvm::cl::opt<bool>
+undef_macros("undef", llvm::cl::value_desc("macro"), llvm::cl::desc("undef all system defines"));
+
static llvm::cl::list<std::string>
D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
llvm::cl::desc("Predefine the specified macro"));
@@ -1099,8 +983,8 @@ static llvm::cl::opt<bool>
nostdinc("nostdinc", llvm::cl::desc("Disable standard #include directories"));
static llvm::cl::opt<bool>
-nostdclanginc("nostdclanginc",
- llvm::cl::desc("Disable standard clang #include directories"));
+nobuiltininc("nobuiltininc",
+ llvm::cl::desc("Disable builtin #include directories"));
// Various command line options. These four add directories to each chain.
static llvm::cl::list<std::string>
@@ -1240,7 +1124,7 @@ void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
Init.AddDefaultEnvVarPaths(Lang);
- if (!nostdclanginc)
+ if (!nobuiltininc)
AddClangIncludePaths(Argv0, &Init);
if (!nostdinc)
@@ -1367,7 +1251,7 @@ public:
PreprocessorInitOptions InitOpts;
InitializePreprocessorInitOptions(InitOpts);
- if (InitializePreprocessor(*PP, InitOpts))
+ if (InitializePreprocessor(*PP, InitOpts, undef_macros))
return 0;
return PP.take();
@@ -1493,6 +1377,8 @@ static void InitializeCompileOptions(CompileOptions &Opts,
Opts.DisableRedZone = DisableRedZone;
Opts.NoImplicitFloat = NoImplicitFloat;
+
+ Opts.MergeAllConstants = !NoMergeConstants;
}
//===----------------------------------------------------------------------===//
@@ -1681,14 +1567,7 @@ public:
// Output diags both where requested...
Chain1.reset(Normal);
// .. and to our log file.
- Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile,
- !NoShowColumn,
- !NoCaretDiagnostics,
- !NoShowLocation,
- PrintSourceRangeInfo,
- PrintDiagnosticOption,
- !NoDiagnosticsFixIt,
- MessageLength));
+ Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
}
virtual void setLangOptions(const LangOptions *LO) {
@@ -1862,8 +1741,8 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
Features, Context));
if (!Consumer.get()) {
- fprintf(stderr, "Unexpected program action!\n");
- HadErrors = true;
+ PP.getDiagnostics().Report(FullSourceLoc(),
+ diag::err_fe_invalid_ast_action);
return;
}
@@ -2082,25 +1961,25 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
if (InitializeSourceManager(PP, InFile))
return;
}
-
+
// If we have an ASTConsumer, run the parser with it.
if (Consumer) {
CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *) = 0;
void *CreateCodeCompleterData = 0;
-
+
if (!CodeCompletionAt.FileName.empty()) {
// Tell the source manager to chop off the given file at a specific
// line and column.
- if (const FileEntry *Entry
+ if (const FileEntry *Entry
= PP.getFileManager().getFile(CodeCompletionAt.FileName)) {
// Truncate the named file at the given line/column.
PP.getSourceManager().truncateFileAt(Entry, CodeCompletionAt.Line,
CodeCompletionAt.Column);
-
+
// Set up the creation routine for code-completion.
CreateCodeCompleter = BuildPrintingCodeCompleter;
} else {
- PP.getDiagnostics().Report(FullSourceLoc(),
+ PP.getDiagnostics().Report(FullSourceLoc(),
diag::err_fe_invalid_code_complete_file)
<< CodeCompletionAt.FileName;
}
@@ -2174,11 +2053,9 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
// handles. Also, we don't want to try to erase an open file.
OS.reset();
- if ((HadErrors || (PP.getDiagnostics().getNumErrors() != 0)) &&
- !OutPath.isEmpty()) {
- // If we had errors, try to erase the output file.
+ // If we had errors, try to erase the output file.
+ if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
OutPath.eraseFromDisk();
- }
}
/// ProcessInputFile - Process a single AST input file with the specified state.
@@ -2233,11 +2110,9 @@ static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
// handles. Also, we don't want to try to erase an open file.
OS.reset();
- if ((HadErrors || (PP.getDiagnostics().getNumErrors() != 0)) &&
- !OutPath.isEmpty()) {
- // If we had errors, try to erase the output file.
+ // If we had errors, try to erase the output file.
+ if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
OutPath.eraseFromDisk();
- }
}
static llvm::cl::list<std::string>
@@ -2276,6 +2151,16 @@ int main(int argc, char **argv) {
if (InputFilenames.empty())
InputFilenames.push_back("-");
+ // Initialize the diagnostic options.
+ DiagOpts.ShowColumn = !NoShowColumn;
+ DiagOpts.ShowLocation = !NoShowLocation;
+ DiagOpts.ShowCarets = !NoCaretDiagnostics;
+ DiagOpts.ShowFixits = !NoDiagnosticsFixIt;
+ DiagOpts.ShowSourceRanges = PrintSourceRangeInfo;
+ DiagOpts.ShowOptionNames = PrintDiagnosticOption;
+ DiagOpts.ShowColors = PrintColorDiagnostic;
+ DiagOpts.MessageLength = MessageLength;
+
// Create the diagnostic client for reporting errors or for
// implementing -verify.
llvm::OwningPtr<DiagnosticClient> DiagClient;
@@ -2292,26 +2177,7 @@ int main(int argc, char **argv) {
}
} else if (HTMLDiag.empty()) {
// Print diagnostics to stderr by default.
-
- // If -fmessage-length=N was not specified, determine whether this
- // is a terminal and, if so, implicitly define -fmessage-length
- // appropriately.
- if (MessageLength.getNumOccurrences() == 0)
- MessageLength.setValue(llvm::sys::Process::StandardErrColumns());
-
- if (!NoColorDiagnostic) {
- NoColorDiagnostic.setValue(!llvm::sys::Process::StandardErrHasColors());
- }
-
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(),
- !NoShowColumn,
- !NoCaretDiagnostics,
- !NoShowLocation,
- PrintSourceRangeInfo,
- PrintDiagnosticOption,
- !NoDiagnosticsFixIt,
- MessageLength,
- !NoColorDiagnostic));
+ DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
} else {
DiagClient.reset(CreateHTMLDiagnosticClient(HTMLDiag));
}
@@ -2338,18 +2204,14 @@ int main(int argc, char **argv) {
llvm::llvm_install_error_handler(LLVMErrorHandler,
static_cast<void*>(&Diags));
- // -I- is a deprecated GCC feature, scan for it and reject it.
- for (unsigned i = 0, e = I_dirs.size(); i != e; ++i) {
- if (I_dirs[i] == "-") {
- Diags.Report(FullSourceLoc(), diag::err_pp_I_dash_not_supported);
- I_dirs.erase(I_dirs.begin()+i);
- --i;
- }
- }
+ // Initialize base triple. If a -triple option has been specified, use
+ // that triple. Otherwise, default to the host triple.
+ llvm::Triple Triple(TargetTriple);
+ if (Triple.getTriple().empty())
+ Triple = llvm::Triple(llvm::sys::getHostTriple());
// Get information about the target being compiled for.
- llvm::Triple Triple = CreateTargetTriple();
- llvm::OwningPtr<TargetInfo>
+ llvm::OwningPtr<TargetInfo>
Target(TargetInfo::CreateTargetInfo(Triple.getTriple()));
if (Target == 0) {
@@ -2390,8 +2252,8 @@ int main(int argc, char **argv) {
continue;
}
- /// Create a SourceManager object. This tracks and owns all the file
- /// buffers allocated to a translation unit.
+ // Create a SourceManager object. This tracks and owns all the file
+ // buffers allocated to a translation unit.
if (!SourceMgr)
SourceMgr.reset(new SourceManager());
else
@@ -2415,26 +2277,21 @@ int main(int argc, char **argv) {
*SourceMgr.get(), HeaderInfo);
llvm::OwningPtr<Preprocessor> PP(PPFactory.CreatePreprocessor());
-
if (!PP)
continue;
- // Handle generating dependencies, if requested
+ // Handle generating dependencies, if requested.
if (!DependencyFile.empty()) {
- llvm::raw_ostream *DependencyOS;
if (DependencyTargets.empty()) {
- // FIXME: Use a proper diagnostic
- llvm::errs() << "-dependency-file requires at least one -MT option\n";
- HadErrors = true;
+ Diags.Report(FullSourceLoc(), diag::err_fe_dependency_file_requires_MT);
continue;
}
std::string ErrStr;
- DependencyOS =
+ llvm::raw_ostream *DependencyOS =
new llvm::raw_fd_ostream(DependencyFile.c_str(), ErrStr);
if (!ErrStr.empty()) {
- // FIXME: Use a proper diagnostic
- llvm::errs() << "unable to open dependency file: " + ErrStr;
- HadErrors = true;
+ Diags.Report(FullSourceLoc(), diag::err_fe_error_opening)
+ << DependencyFile << ErrStr;
continue;
}
@@ -2483,5 +2340,5 @@ int main(int argc, char **argv) {
// -time-passes usable.
llvm::llvm_shutdown();
- return HadErrors || (Diags.getNumErrors() != 0);
+ return (Diags.getNumErrors() != 0);
}
diff --git a/tools/wpa/clang-wpa.cpp b/tools/wpa/clang-wpa.cpp
index fa2326dc2ba4..346634b6f617 100644
--- a/tools/wpa/clang-wpa.cpp
+++ b/tools/wpa/clang-wpa.cpp
@@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/CallGraph.h"
-
+#include "clang/Frontend/ASTUnit.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
@@ -56,7 +56,7 @@ int main(int argc, char **argv) {
CG.reset(new CallGraph());
for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
- CG->addTU(*ASTUnits[i]);
+ CG->addTU(ASTUnits[i]->getASTContext());
CG->ViewCallGraph();
}
diff --git a/www/UniversalDriver.html b/www/UniversalDriver.html
index f66151a49345..82ccc8ded776 100644
--- a/www/UniversalDriver.html
+++ b/www/UniversalDriver.html
@@ -77,6 +77,9 @@ welcome!</p>
wiki page for their work to support the ARM EABI provide an interesting
glimpse into how related issues impact the operating system distribution.</li>
+ <li><a href="http://icculus.org/fatelf/">FatELF</a> is a proposal for bringing
+ Mac OS X like "Universal Binary" support to ELF based platforms.</li>
+
</ul>
</div>
diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index 4184ce6d4010..8ecd1bba551a 100644
--- a/www/analyzer/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
@@ -1 +1 @@
-<b><a href="http://checker.minormatter.com/checker-225.tar.bz2">checker-225.tar.bz2</a></b> (built October 21, 2009)
+<b><a href="http://checker.minormatter.com/checker-226.tar.bz2">checker-226.tar.bz2</a></b> (built October 29, 2009)
diff --git a/www/cxx_status.html b/www/cxx_status.html
index ecfc8a88dd73..e1df3befc5b7 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -24,7 +24,7 @@
<!--*************************************************************************-->
<h1>C++ Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2009-10-20 23:10:15 +0200 (Tue, 20 Oct 2009) $</p>
+<p>Last updated: $Date: 2009-10-30 15:54:38 +0100 (Fri, 30 Oct 2009) $</p>
<p>
This page tracks the status of C++ support in Clang.<br>
@@ -327,6 +327,7 @@ welcome!</p>
<td class="na">N/A</td>
<td class="complete"></td>
<td class="na">N/A</td>
+ <td></td>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;3.3.6 [basic.scope.class]</td>
@@ -407,6 +408,7 @@ welcome!</p>
<td class="na">N/A</td>
<td class="medium"></td>
<td class="na">N/A</td>
+ <td></td>
</tr>
<tr><td>&nbsp;&nbsp;3.5 [basic.link]</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>&nbsp;&nbsp;3.6 [basic.start]</td><td></td><td></td><td></td><td></td><td></td></tr>
@@ -732,7 +734,7 @@ welcome!</p>
<td class="advanced"></td>
<td class="advanced"></td>
<td></td>
- <td>Dereferenced member function pointers have the wrong type.</td>
+ <td>Dereferenced member function pointers have the wrong type(see FIXME in CheckPointerToMemberOperands).</td>
</tr>
<tr>
<td>&nbsp;&nbsp;5.6 [expr.mul]</td>
@@ -1521,6 +1523,7 @@ welcome!</p>
<td class="advanced" align="center"></td>
<td class="advanced" align="center"></td>
<td class="advanced" align="center"></td>
+ <td></td>
</tr>
<tr>
<td>&nbsp;&nbsp;12.4 [class.dtor]</td>
@@ -1606,6 +1609,7 @@ welcome!</p>
<td class="advanced" align="center"></td>
<td class="advanced" align="center"></td>
<td class="na" align="center">N/A</td>
+ <td></td>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13.3.1.2 [over.match.oper]</td>
@@ -1661,6 +1665,7 @@ welcome!</p>
<td class="advanced" align="center"></td>
<td class="advanced" align="center"></td>
<td class="na" align="center">N/A</td>
+ <td></td>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13.3.3.1 [over.best.ics]</td>
@@ -1792,7 +1797,7 @@ welcome!</p>
</tr>
<tr>
<td>14 [temp]</td>
- <td class="basic" align="center">N/A</td>
+ <td class="medium" align="center"></td>
<td class="basic" align="center"></td>
<td class="basic" align="center"></td>
<td class="broken" align="center"></td>
@@ -2075,11 +2080,12 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;14.7.2 [temp.explicit]</td>
+ <td class="complete" align="center"></td>
<td class="advanced" align="center"></td>
- <td class="medium" align="center"></td>
- <td class="medium" align="center"></td>
- <td class="broken" align="center"></td>
- <td></td>
+ <td class="advanced" align="center"></td>
+ <td class="complete" align="center"></td>
+ <td>Cannot test paragraph 11 until access control is implemented.<br/>
+ ASTs do not carry enough information to reproduce source code accurately.</td>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;14.7.3 [temp.expl.spec]</td>