diff options
486 files changed, 22043 insertions, 9947 deletions
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 6556bb4e6a8c..43733f779378 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -441,43 +441,42 @@ 1AA963AB10D8576800786C86 /* FullExpr.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = FullExpr.h; path = clang/AST/FullExpr.h; sourceTree = "<group>"; tabWidth = 2; }; 1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; }; 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; }; - 1ABD23B11182449800A48E65 /* APValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APValue.cpp; sourceTree = "<group>"; }; - 1ABD23B21182449800A48E65 /* ASTConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTConsumer.cpp; sourceTree = "<group>"; }; - 1ABD23B31182449800A48E65 /* ASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTContext.cpp; sourceTree = "<group>"; }; - 1ABD23B41182449800A48E65 /* ASTDiagnostic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTDiagnostic.cpp; sourceTree = "<group>"; }; - 1ABD23B51182449800A48E65 /* ASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTImporter.cpp; sourceTree = "<group>"; }; - 1ABD23B61182449800A48E65 /* AttrImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttrImpl.cpp; sourceTree = "<group>"; }; - 1ABD23B71182449800A48E65 /* CXXInheritance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CXXInheritance.cpp; sourceTree = "<group>"; }; - 1ABD23B81182449800A48E65 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Decl.cpp; sourceTree = "<group>"; }; - 1ABD23B91182449800A48E65 /* DeclarationName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclarationName.cpp; sourceTree = "<group>"; }; - 1ABD23BA1182449800A48E65 /* DeclBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclBase.cpp; sourceTree = "<group>"; }; - 1ABD23BB1182449800A48E65 /* DeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclCXX.cpp; sourceTree = "<group>"; }; - 1ABD23BC1182449800A48E65 /* DeclFriend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclFriend.cpp; sourceTree = "<group>"; }; - 1ABD23BD1182449800A48E65 /* DeclGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclGroup.cpp; sourceTree = "<group>"; }; - 1ABD23BE1182449800A48E65 /* DeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclObjC.cpp; sourceTree = "<group>"; }; - 1ABD23BF1182449800A48E65 /* DeclPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclPrinter.cpp; sourceTree = "<group>"; }; - 1ABD23C01182449800A48E65 /* DeclTemplate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclTemplate.cpp; sourceTree = "<group>"; }; - 1ABD23C11182449800A48E65 /* Expr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Expr.cpp; sourceTree = "<group>"; }; - 1ABD23C21182449800A48E65 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExprConstant.cpp; sourceTree = "<group>"; }; - 1ABD23C31182449800A48E65 /* ExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExprCXX.cpp; sourceTree = "<group>"; }; - 1ABD23C41182449800A48E65 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FullExpr.cpp; sourceTree = "<group>"; }; - 1ABD23C51182449800A48E65 /* InheritViz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InheritViz.cpp; sourceTree = "<group>"; }; - 1ABD23C61182449800A48E65 /* NestedNameSpecifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NestedNameSpecifier.cpp; sourceTree = "<group>"; }; - 1ABD23C71182449800A48E65 /* ParentMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentMap.cpp; sourceTree = "<group>"; }; - 1ABD23C81182449800A48E65 /* RecordLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RecordLayout.cpp; sourceTree = "<group>"; }; - 1ABD23C91182449800A48E65 /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RecordLayoutBuilder.cpp; sourceTree = "<group>"; }; - 1ABD23CA1182449800A48E65 /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordLayoutBuilder.h; sourceTree = "<group>"; }; - 1ABD23CB1182449800A48E65 /* Stmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Stmt.cpp; sourceTree = "<group>"; }; - 1ABD23CC1182449800A48E65 /* StmtDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StmtDumper.cpp; sourceTree = "<group>"; }; - 1ABD23CD1182449800A48E65 /* StmtIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StmtIterator.cpp; sourceTree = "<group>"; }; - 1ABD23CE1182449800A48E65 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StmtPrinter.cpp; sourceTree = "<group>"; }; - 1ABD23CF1182449800A48E65 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StmtProfile.cpp; sourceTree = "<group>"; }; - 1ABD23D01182449800A48E65 /* StmtViz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StmtViz.cpp; sourceTree = "<group>"; }; - 1ABD23D11182449800A48E65 /* TemplateBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateBase.cpp; sourceTree = "<group>"; }; - 1ABD23D21182449800A48E65 /* TemplateName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateName.cpp; sourceTree = "<group>"; }; - 1ABD23D31182449800A48E65 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Type.cpp; sourceTree = "<group>"; }; - 1ABD23D41182449800A48E65 /* TypeLoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeLoc.cpp; sourceTree = "<group>"; }; - 1ABD23D51182449800A48E65 /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypePrinter.cpp; sourceTree = "<group>"; }; + 1ABD23B11182449800A48E65 /* APValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = APValue.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B21182449800A48E65 /* ASTConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ASTConsumer.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B31182449800A48E65 /* ASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ASTContext.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B41182449800A48E65 /* ASTDiagnostic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ASTDiagnostic.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B51182449800A48E65 /* ASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ASTImporter.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B61182449800A48E65 /* AttrImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = AttrImpl.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B71182449800A48E65 /* CXXInheritance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = CXXInheritance.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B81182449800A48E65 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = Decl.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23B91182449800A48E65 /* DeclarationName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclarationName.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BA1182449800A48E65 /* DeclBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclBase.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BB1182449800A48E65 /* DeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BC1182449800A48E65 /* DeclFriend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclFriend.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BD1182449800A48E65 /* DeclGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclGroup.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BE1182449800A48E65 /* DeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclObjC.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23BF1182449800A48E65 /* DeclPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclPrinter.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C01182449800A48E65 /* DeclTemplate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = DeclTemplate.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C11182449800A48E65 /* Expr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = Expr.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C21182449800A48E65 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C31182449800A48E65 /* ExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C41182449800A48E65 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = FullExpr.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C51182449800A48E65 /* InheritViz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = InheritViz.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C61182449800A48E65 /* NestedNameSpecifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = NestedNameSpecifier.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C71182449800A48E65 /* ParentMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ParentMap.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C81182449800A48E65 /* RecordLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = RecordLayout.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23C91182449800A48E65 /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23CB1182449800A48E65 /* Stmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = Stmt.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23CC1182449800A48E65 /* StmtDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = StmtDumper.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23CD1182449800A48E65 /* StmtIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = StmtIterator.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23CE1182449800A48E65 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = StmtPrinter.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23CF1182449800A48E65 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D01182449800A48E65 /* StmtViz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = StmtViz.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D11182449800A48E65 /* TemplateBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateBase.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D21182449800A48E65 /* TemplateName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateName.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D31182449800A48E65 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = Type.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D41182449800A48E65 /* TypeLoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TypeLoc.cpp; sourceTree = "<group>"; tabWidth = 2; }; + 1ABD23D51182449800A48E65 /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TypePrinter.cpp; sourceTree = "<group>"; tabWidth = 2; }; 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInstance.cpp; path = lib/Frontend/CompilerInstance.cpp; sourceTree = "<group>"; }; 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInvocation.cpp; path = lib/Frontend/CompilerInvocation.cpp; sourceTree = "<group>"; }; 1ACB57DD1105820D0047B991 /* DeclXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclXML.cpp; path = lib/Frontend/DeclXML.cpp; sourceTree = "<group>"; }; @@ -1494,7 +1493,6 @@ 1ABD23C71182449800A48E65 /* ParentMap.cpp */, 1ABD23C81182449800A48E65 /* RecordLayout.cpp */, 1ABD23C91182449800A48E65 /* RecordLayoutBuilder.cpp */, - 1ABD23CA1182449800A48E65 /* RecordLayoutBuilder.h */, 1ABD23CB1182449800A48E65 /* Stmt.cpp */, 1ABD23CC1182449800A48E65 /* StmtDumper.cpp */, 1ABD23CD1182449800A48E65 /* StmtIterator.cpp */, diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html index daec6b019415..5ef5dd842a6d 100644 --- a/docs/InternalsManual.html +++ b/docs/InternalsManual.html @@ -532,12 +532,12 @@ source code of the program. Important design points include:</p> </ol> <p>In practice, the SourceLocation works together with the SourceManager class -to encode two pieces of information about a location: it's spelling location -and it's instantiation location. For most tokens, these will be the same. However, -for a macro expansion (or tokens that came from a _Pragma directive) these will -describe the location of the characters corresponding to the token and the -location where the token was used (i.e. the macro instantiation point or the -location of the _Pragma itself).</p> +to encode two pieces of information about a location: its spelling location +and its instantiation location. For most tokens, these will be the same. +However, for a macro expansion (or tokens that came from a _Pragma directive) +these will describe the location of the characters corresponding to the token +and the location where the token was used (i.e. the macro instantiation point +or the location of the _Pragma itself).</p> <p>The Clang front-end inherently depends on the location of a token being tracked correctly. If it is ever incorrect, the front-end may get confused and diff --git a/docs/UsersManual.html b/docs/UsersManual.html index 7d7f2631ab5e..5c5f6f916cf6 100644 --- a/docs/UsersManual.html +++ b/docs/UsersManual.html @@ -36,6 +36,7 @@ td { <ul> <li><a href="#diagnostics_display">Controlling How Clang Displays Diagnostics</a></li> <li><a href="#diagnostics_mappings">Diagnostic Mappings</a></li> + <li><a href="#diagnostics_categories">Diagnostic Categories</a><li> <li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li> <li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li> </ul> @@ -286,6 +287,30 @@ diagnostic. This information tells you the flag needed to enable or disable the diagnostic, either from the command line or through <a href="#pragma_GCC_diagnostic">#pragma GCC diagnostic</a>.</dd> +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> +<dt id="opt_fdiagnostics-show-category"><b>-fdiagnostics-show-category=none/id/name</b>: +Enable printing category information in diagnostic line.</dt> +<dd>This option, which defaults to "none", +controls whether or not Clang prints the category associated with a diagnostic +when emitting it. Each diagnostic may or many not have an associated category, +if it has one, it is listed in the diagnostic categorization field of the +diagnostic line (in the []'s).</p> + +<p>For example, a format string warning will produce these three renditions +based on the setting of this option:</p> + +<pre> + t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat] + t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat<b>,1</b>] + t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat<b>,Format String</b>] +</pre> + +<p>This category can be used by clients that want to group diagnostics by +category, so it should be a high level category. We want dozens of these, not +hundreds or thousands of them.</p> +</dd> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <dt id="opt_fdiagnostics-fixit-info"><b>-f[no-]diagnostics-fixit-info</b>: @@ -393,6 +418,10 @@ it:</p> <li>An option that indicates how to control the diagnostic (for diagnostics that support it) [<a href="#opt_fdiagnostics-show-option">-fdiagnostics-show-option</a>].</li> +<li>A <a href="#diagnostics_categories">high-level category</a> for the + diagnostic for clients that want to group diagnostics by class (for + diagnostics that support it) [<a + href="#opt_fdiagnostics-show-category">-fdiagnostics-show-category</a>].</li> <li>The line of source code that the issue occurs on, along with a caret and ranges that indicate the important locations [<a href="opt_fcaret-diagnostics">-fcaret-diagnostics</a>].</li> @@ -407,6 +436,7 @@ it:</p> <p>For more information please see <a href="#cl_diag_formatting">Formatting of Diagnostics</a>.</p> + <h4 id="diagnostics_mappings">Diagnostic Mappings</h4> <p>All diagnostics are mapped into one of these 5 classes:</p> @@ -420,7 +450,23 @@ Diagnostics</a>.</p> <li>Fatal</li> </ul></p> -<h4 id="diagnostics_commandline">Controlling Diagnostics via Command Line Flags</h4> +<h4 id="diagnostics_categories">Diagnostic Categories</h4> + +<p>Though not shown by default, diagnostics may each be associated with a + high-level category. This category is intended to make it possible to triage + builds that produce a large number of errors or warnings in a grouped way. +</p> + +<p>Categories are not shown by default, but they can be turned on with the +<a href="#opt_fdiagnostics-show-category">-fdiagnostics-show-category</a> option. +When set to "<tt>name</tt>", the category is printed textually in the diagnostic +output. When it is set to "<tt>id</tt>", a category number is printed. The +mapping of category names to category id's can be obtained by running '<tt>clang + --print-diagnostic-categories</tt>'. +</p> + +<h4 id="diagnostics_commandline">Controlling Diagnostics via Command Line + Flags</h4> <p>-W flags, -pedantic, etc</p> diff --git a/docs/tools/clang.pod b/docs/tools/clang.pod index 42cf8fa2d711..0c1ab574d535 100644 --- a/docs/tools/clang.pod +++ b/docs/tools/clang.pod @@ -50,10 +50,13 @@ parse errors. The output of this stage is an "Abstract Syntax Tree" (AST). =item B<Code Generation and Optimization> This stage translates an AST into low-level intermediate code (known as "LLVM -IR") and ultimately to machine code (depending on the optimization level). This -phase is responsible for optimizing the generated code and handling -target-specfic code generation. The output of this stage is typically called a -".s" file or "assembly" file. +IR") and ultimately to machine code. This phase is responsible for optimizing +the generated code and handling target-specfic code generation. The output of +this stage is typically called a ".s" file or "assembly" file. + +Clang also supports the use of an integrated assembler, in which the code +generator produces object files directly. This avoids the overhead of generating +the ".s" file and of calling the target assembler. =item B<Assembler> @@ -325,17 +328,21 @@ Pass I<arg> to the assembler. =item B<-Xclang> I<arg> -Pass I<arg> to the clang compiler. +Pass I<arg> to the clang compiler frontend. =item B<-Xlinker> I<arg> Pass I<arg> to the linker. +=item B<-mllvm> I<arg> + +Pass I<arg> to the LLVM backend. + =item B<-Xpreprocessor> I<arg> Pass I<arg> to the preprocessor. -=item B<-o> I<file> +=item B<-o> I<file> Write output to I<file>. @@ -359,6 +366,12 @@ Print the paths used for finding libraries and programs. Save intermediate compilation results. +=item B<-integrated-as> B<-no-integrated-as> + +Used to enable and disable, respectively, the use of the integrated +assembler. Whether the integrated assembler is on by default is target +dependent. + =item B<-time> Time individual commands. diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 1bf5a4688a2c..86926bd683ba 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -343,6 +343,12 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range); CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); /** + * \brief Determine if the source location occurs within the main file + * of the translation unit (as opposed to an included header). + */ +CINDEX_LINKAGE unsigned clang_isFromMainFile(CXSourceLocation loc); + +/** * @} */ @@ -648,7 +654,6 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); */ enum CXCursorKind { /* Declarations */ - CXCursor_FirstDecl = 1, /** * \brief A declaration whose specific kind is not exposed via this * interface. @@ -700,11 +705,15 @@ enum CXCursorKind { CXCursor_ObjCCategoryImplDecl = 19, /** \brief A typedef */ CXCursor_TypedefDecl = 20, - /** \brief A C++ class method. */ CXCursor_CXXMethod = 21, + /** \brief A C++ namespace. */ + CXCursor_Namespace = 22, + /** \brief A linkage specification, e.g. 'extern "C"'. */ + CXCursor_LinkageSpec = 23, - CXCursor_LastDecl = 21, + CXCursor_FirstDecl = CXCursor_UnexposedDecl, + CXCursor_LastDecl = CXCursor_LinkageSpec, /* References */ CXCursor_FirstRef = 40, /* Decl references */ @@ -807,7 +816,8 @@ enum CXCursorKind { CXCursor_IBActionAttr = 401, CXCursor_IBOutletAttr = 402, - CXCursor_LastAttr = CXCursor_IBOutletAttr, + CXCursor_IBOutletCollectionAttr = 403, + CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -1021,6 +1031,124 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); */ /** + * \defgroup CINDEX_TYPES Type information for CXCursors + * + * @{ + */ + +/** + * \brief Describes the kind of type + */ +enum CXTypeKind { + /** + * \brief Reprents an invalid type (e.g., where no type is available). + */ + CXType_Invalid = 0, + + /** + * \brief A type whose specific kind is not exposed via this + * interface. + */ + CXType_Unexposed = 1, + + /* Builtin types */ + CXType_Void = 2, + CXType_Bool = 3, + CXType_Char_U = 4, + CXType_UChar = 5, + CXType_Char16 = 6, + CXType_Char32 = 7, + CXType_UShort = 8, + CXType_UInt = 9, + CXType_ULong = 10, + CXType_ULongLong = 11, + CXType_UInt128 = 12, + CXType_Char_S = 13, + CXType_SChar = 14, + CXType_WChar = 15, + CXType_Short = 16, + CXType_Int = 17, + CXType_Long = 18, + CXType_LongLong = 19, + CXType_Int128 = 20, + CXType_Float = 21, + CXType_Double = 22, + CXType_LongDouble = 23, + CXType_NullPtr = 24, + CXType_Overload = 25, + CXType_Dependent = 26, + CXType_ObjCId = 27, + CXType_ObjCClass = 28, + CXType_ObjCSel = 29, + CXType_FirstBuiltin = CXType_Void, + CXType_LastBuiltin = CXType_ObjCSel, + + CXType_Complex = 100, + CXType_Pointer = 101, + CXType_BlockPointer = 102, + CXType_LValueReference = 103, + CXType_RValueReference = 104, + CXType_Record = 105, + CXType_Enum = 106, + CXType_Typedef = 107, + CXType_ObjCInterface = 108, + CXType_ObjCObjectPointer = 109 +}; + +/** + * \brief The type of an element in the abstract syntax tree. + * + */ +typedef struct { + enum CXTypeKind kind; + void *data[2]; +} CXType; + +/** + * \brief Retrieve the type of a CXCursor (if any). + */ +CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C); + +/** + * \determine Determine whether two CXTypes represent the same type. + * + * \returns non-zero if the CXTypes represent the same type and + zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B); + +/** + * \brief Return the canonical type for a CXType. + * + * Clang's type system explicitly models typedefs and all the ways + * a specific type can be represented. The canonical type is the underlying + * type with all the "sugar" removed. For example, if 'T' is a typedef + * for 'int', the canonical type for 'T' would be 'int'. + */ +CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T); + +/** + * \brief For pointer types, returns the type of the pointee. + * + */ +CINDEX_LINKAGE CXType clang_getPointeeType(CXType T); + +/** + * \brief Return the cursor for the declaration of the given type. + */ +CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T); + + +/** + * \brief Retrieve the spelling of a given CXTypeKind. + */ +CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K); + +/** + * @} + */ + +/** * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors * * These routines provide the ability to traverse the abstract syntax tree @@ -1220,6 +1348,24 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); */ /** + * \defgroup CINDEX_CPP C++ AST introspection + * + * The routines in this group provide access information in the ASTs specific + * to C++ language features. + * + * @{ + */ + +/** + * \brief Determine if a C++ member function is declared 'static'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); + +/** + * @} + */ + +/** * \defgroup CINDEX_LEX Token extraction and manipulation * * The routines in this group provide access to the tokens within a @@ -1649,6 +1795,21 @@ CINDEX_LINKAGE unsigned clang_getNumCompletionChunks(CXCompletionString completion_string); /** + * \brief Determine the priority of this code completion. + * + * The priority of a code completion indicates how likely it is that this + * particular completion is the completion that the user will select. The + * priority is selected by various internal heuristics. + * + * \param completion_string The completion string to query. + * + * \returns The priority of this completion string. Smaller values indicate + * higher-priority (more likely) completions. + */ +CINDEX_LINKAGE unsigned +clang_getCompletionPriority(CXCompletionString completion_string); + +/** * \brief Contains the results of code-completion. * * This data structure contains the results of code completion, as diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 53bb785c49d2..06113954fc48 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -16,6 +16,7 @@ namespace clang { class ASTContext; + class CXXRecordDecl; class DeclGroupRef; class TagDecl; class HandleTagDeclDefinition; @@ -68,6 +69,17 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// \brief Callback involved at the end of a translation unit to + /// notify the consumer that a vtable for the given C++ class is + /// required. + /// + /// \param RD The class whose vtable was used. + /// + /// \param DefinitionRequired Whether a definition of this vtable is + /// required in this translation unit; otherwise, it is only needed if + /// it was actually used. + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index f8a8f179ae58..87a12cde2ad2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -96,11 +96,10 @@ class ASTContext { llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; - llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; + llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<DependentNameType> DependentNameTypes; - llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; + llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -483,7 +482,7 @@ public: /// This gets the struct used to keep track of pointer to blocks, complete /// with captured variables. QualType getBlockParmType(bool BlockHasCopyDispose, - llvm::SmallVector<const Expr *, 8> &BDRDs); + llvm::SmallVectorImpl<const Expr *> &Layout); /// This builds the struct used for __block variables. QualType BuildByRefType(const char *DeclName, QualType Ty); @@ -613,8 +612,9 @@ public: const TemplateArgumentListInfo &Args, QualType Canon = QualType()); - QualType getQualifiedNameType(NestedNameSpecifier *NNS, - QualType NamedType); + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType); QualType getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -623,19 +623,16 @@ public: NestedNameSpecifier *NNS, const TemplateSpecializationType *TemplateId, QualType Canon = QualType()); - QualType getElaboratedType(QualType UnderlyingType, - ElaboratedType::TagKind Tag); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **Protocols = 0, - unsigned NumProtocols = 0); + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); + + QualType getObjCObjectType(QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols); - /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the - /// given interface decl and the conforming protocol list. - QualType getObjCObjectPointerType(QualType OIT, - ObjCProtocolDecl **ProtocolList = 0, - unsigned NumProtocols = 0, - unsigned Quals = 0); + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type + /// for the given ObjCObjectType. + QualType getObjCObjectPointerType(QualType OIT); /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); @@ -913,6 +910,9 @@ public: CharUnits getTypeAlignInChars(QualType T); CharUnits getTypeAlignInChars(const Type *T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T); + std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T); + /// getPreferredTypeAlign - Return the "preferred" alignment of the specified /// type for the current target in bits. This can be different than the ABI /// alignment in cases where it is beneficial for performance to overalign @@ -1184,8 +1184,8 @@ public: // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); - bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, - const ObjCInterfaceType *RHS); + bool canAssignObjCInterfaces(const ObjCObjectType *LHS, + const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1196,6 +1196,8 @@ public: // Functions for calculating composite types QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); + + QualType mergeObjCGCQualifiers(QualType, QualType); /// UsualArithmeticConversionsType - handles the various conversions /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) @@ -1270,6 +1272,15 @@ public: TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); + /// \brief Add a deallocation callback that will be invoked when the + /// ASTContext is destroyed. + /// + /// \brief Callback A callback function that will be invoked on destruction. + /// + /// \brief Data Pointer data that will be provided to the callback function + /// when it is called. + void AddDeallocation(void (*Callback)(void*), void *Data); + private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT void operator=(const ASTContext&); // DO NOT IMPLEMENT @@ -1284,16 +1295,21 @@ private: const FieldDecl *Field, bool OutermostType = false, bool EncodingProperty = false); - + const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); private: + /// \brief A set of deallocations that should be performed when the + /// ASTContext is destroyed. + llvm::SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations; + // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; friend class DeclContext; + friend class DeclarationNameTable; void ReleaseDeclContextMaps(); }; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 19744931762b..3240e50b0787 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -23,9 +23,10 @@ using llvm::dyn_cast; namespace clang { class ASTContext; + class IdentifierInfo; + class ObjCInterfaceDecl; } - // Defined in ASTContext.h void *operator new(size_t Bytes, clang::ASTContext &C, size_t Alignment = 16) throw (); @@ -44,6 +45,7 @@ public: enum Kind { Alias, Aligned, + AlignMac68k, AlwaysInline, AnalyzerNoReturn, // Clang-specific. Annotate, @@ -63,8 +65,10 @@ public: GNUInline, Hiding, IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. + IBOutletCollectionKind, // Clang-specific. IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. Malloc, + MaxFieldAlignment, NoDebug, NoInline, NonNull, @@ -79,13 +83,13 @@ public: NSReturnsNotRetained, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, - PragmaPack, Pure, Regparm, ReqdWorkGroupSize, // OpenCL-specific Section, Sentinel, StdCall, + ThisCall, TransparentUnion, Unavailable, Unused, @@ -183,11 +187,14 @@ public: \ DEF_SIMPLE_ATTR(Packed); -class PragmaPackAttr : public Attr { +/// \brief Attribute for specifying a maximum field alignment; this is only +/// valid on record decls. +class MaxFieldAlignmentAttr : public Attr { unsigned Alignment; public: - PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {} + MaxFieldAlignmentAttr(unsigned alignment) + : Attr(MaxFieldAlignment), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } @@ -196,11 +203,13 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == PragmaPack; + return A->getKind() == MaxFieldAlignment; } - static bool classof(const PragmaPackAttr *A) { return true; } + static bool classof(const MaxFieldAlignmentAttr *A) { return true; } }; +DEF_SIMPLE_ATTR(AlignMac68k); + class AlignedAttr : public Attr { unsigned Alignment; public: @@ -317,6 +326,23 @@ public: static bool classof(const IBOutletAttr *A) { return true; } }; +class IBOutletCollectionAttr : public Attr { + const ObjCInterfaceDecl *D; +public: + IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) + : Attr(IBOutletCollectionKind), D(d) {} + + const ObjCInterfaceDecl *getClass() const { return D; } + + virtual Attr *clone(ASTContext &C) const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == IBOutletCollectionKind; + } + static bool classof(const IBOutletCollectionAttr *A) { return true; } +}; + class IBActionAttr : public Attr { public: IBActionAttr() : Attr(IBActionKind) {} @@ -457,6 +483,7 @@ public: DEF_SIMPLE_ATTR(FastCall); DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(ThisCall); DEF_SIMPLE_ATTR(CDecl); DEF_SIMPLE_ATTR(TransparentUnion); DEF_SIMPLE_ATTR(ObjCNSObject); diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt new file mode 100644 index 000000000000..c24ea06aa024 --- /dev/null +++ b/include/clang/AST/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_TARGET_DEFINITIONS StmtNodes.td) +tablegen(StmtNodes.inc + -gen-clang-stmt-nodes) +add_custom_target(ClangStmtNodes + DEPENDS StmtNodes.inc) diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index edd633e8e140..5a84e404a1b6 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -196,7 +196,7 @@ public: /// \brief Determine whether the path from the most-derived type to the /// given base type is ambiguous (i.e., it refers to multiple subobjects of /// the same base type). - bool isAmbiguous(QualType BaseType); + bool isAmbiguous(CanQualType BaseType); /// \brief Whether we are finding multiple paths to detect ambiguities. bool isFindingAmbiguities() const { return FindAmbiguities; } diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 93dcad751221..4afb81dd05eb 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -643,6 +643,24 @@ struct CanProxyAdaptor<TemplateTypeParmType> }; template<> +struct CanProxyAdaptor<ObjCObjectType> + : public CanProxyBase<ObjCObjectType> { + LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, + getInterface) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) + + typedef ObjCObjectPointerType::qual_iterator qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) +}; + +template<> struct CanProxyAdaptor<ObjCObjectPointerType> : public CanProxyBase<ObjCObjectPointerType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 834c9a0c563f..7d5b66e02a28 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -55,7 +55,7 @@ public: QualType getType() const { return Ty; } /// \brief Return the TypeLoc wrapper for the type source info. - TypeLoc getTypeLoc() const; + TypeLoc getTypeLoc() const; // implemented in TypeLoc.h }; /// TranslationUnitDecl - The top declaration context. @@ -138,6 +138,8 @@ public: // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { return Name.getAsString(); } + void printName(llvm::raw_ostream &os) const { return Name.printName(os); } + /// getDeclName - Get the actual, stored name of the declaration, /// which may be a special name. DeclarationName getDeclName() const { return Name; } @@ -265,18 +267,25 @@ public: // \brief Returns true if this is an anonymous namespace declaration. // // For example: + /// \code // namespace { // ... // }; + // \endcode // q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } + /// \brief Return the next extended namespace declaration or null if this + /// is none. NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } + + /// \brief Set the next extended namespace declaration. void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + /// \brief Get the original (first) namespace declaration. NamespaceDecl *getOriginalNamespace() const { if (OrigOrAnonNamespace.getInt()) return const_cast<NamespaceDecl *>(this); @@ -284,6 +293,14 @@ public: return OrigOrAnonNamespace.getPointer(); } + /// \brief Return true if this declaration is an original (first) declaration + /// of the namespace. This is false for non-original (subsequent) namespace + /// declarations and anonymous namespaces. + bool isOriginalNamespace() const { + return getOriginalNamespace() == this; + } + + /// \brief Set the original (first) namespace declaration. void setOriginalNamespace(NamespaceDecl *ND) { if (ND != this) { OrigOrAnonNamespace.setPointer(ND); @@ -502,6 +519,10 @@ private: /// or an Objective-C @catch statement. bool ExceptionVar : 1; + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization (NRVO). + bool NRVOVariable : 1; + friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -509,7 +530,7 @@ protected: StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false), ExceptionVar(false) { + DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -852,6 +873,19 @@ public: } void setExceptionVariable(bool EV) { ExceptionVar = EV; } + /// \brief Determine whether this local variable can be used with the named + /// return value optimization (NRVO). + /// + /// The named return value optimization (NRVO) works by marking certain + /// non-volatile local variables of class type as NRVO objects. These + /// locals can be allocated within the return slot of their containing + /// function, in which case there is no need to copy the object to the + /// return slot when returning from the function. Within the function body, + /// each return that returns the NRVO object will have this variable as its + /// NRVO candidate. + bool isNRVOVariable() const { return NRVOVariable; } + void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. @@ -1390,6 +1424,16 @@ public: /// returns NULL. const TemplateArgumentList *getTemplateSpecializationArgs() const; + /// \brief Retrieve the template argument list as written in the sources, + /// if any. + /// + /// If this function declaration is not a function template specialization + /// or if it had no explicit template argument list, returns NULL. + /// Note that it an explicit template argument list may be written empty, + /// e.g., template<> void foo<>(char* s); + const TemplateArgumentListInfo* + getTemplateSpecializationArgsAsWritten() const; + /// \brief Specify that this function declaration is actually a function /// template specialization. /// @@ -1409,7 +1453,8 @@ public: void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, - TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); + TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, + const TemplateArgumentListInfo *TemplateArgsAsWritten = 0); /// \brief Specifies that this function declaration is actually a /// dependent function template specialization. @@ -1593,7 +1638,19 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} virtual ~TypedefDecl(); + +protected: + typedef Redeclarable<TypedefDecl> redeclarable_base; + virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + public: + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -1631,11 +1688,7 @@ class TagDecl : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { public: // This is really ugly. - typedef ElaboratedType::TagKind TagKind; - static const TagKind TK_struct = ElaboratedType::TK_struct; - static const TagKind TK_union = ElaboratedType::TK_union; - static const TagKind TK_class = ElaboratedType::TK_class; - static const TagKind TK_enum = ElaboratedType::TK_enum; + typedef TagTypeKind TagKind; private: // FIXME: This can be packed into the bitfields in Decl. @@ -1651,6 +1704,12 @@ private: /// in the syntax of a declarator. bool IsEmbeddedInDeclarator : 1; +protected: + // These are used by (and only defined for) EnumDecl. + unsigned NumPositiveBits : 8; + unsigned NumNegativeBits : 8; + +private: SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; @@ -1680,7 +1739,8 @@ protected: TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), TypedefDeclOrQualifier((TypedefDecl*) 0) { - assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); + assert((DK != Enum || TK == TTK_Enum) && + "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; IsDefinition = false; IsEmbeddedInDeclarator = false; @@ -1753,30 +1813,26 @@ public: void setDefinition(bool V) { IsDefinition = V; } const char *getKindName() const { - return ElaboratedType::getNameForTagKind(getTagKind()); + return TypeWithKeyword::getTagTypeKindName(getTagKind()); } - /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST) - /// into a tag kind. It is an error to provide a type specifier - /// which *isn't* a tag kind here. - static TagKind getTagKindForTypeSpec(unsigned TypeSpec); - TagKind getTagKind() const { return TagKind(TagDeclKind); } void setTagKind(TagKind TK) { TagDeclKind = TK; } - bool isStruct() const { return getTagKind() == TK_struct; } - bool isClass() const { return getTagKind() == TK_class; } - bool isUnion() const { return getTagKind() == TK_union; } - bool isEnum() const { return getTagKind() == TK_enum; } + bool isStruct() const { return getTagKind() == TTK_Struct; } + bool isClass() const { return getTagKind() == TTK_Class; } + bool isUnion() const { return getTagKind() == TTK_Union; } + bool isEnum() const { return getTagKind() == TTK_Enum; } TypedefDecl *getTypedefForAnonDecl() const { return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); } - void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; } - + + void setTypedefForAnonDecl(TypedefDecl *TDD); + NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; } @@ -1820,9 +1876,16 @@ class EnumDecl : public TagDecl { /// enumeration declared within the template. EnumDecl *InstantiatedFrom; + // The number of positive and negative bits required by the + // enumerators are stored in the SubclassBits field. + enum { + NumBitsWidth = 8, + NumBitsMask = (1 << NumBitsWidth) - 1 + }; + EnumDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) - : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { + : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); } public: @@ -1845,7 +1908,9 @@ public: /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. void completeDefinition(QualType NewType, - QualType PromotionType); + QualType PromotionType, + unsigned NumPositiveBits, + unsigned NumNegativeBits); // enumerator_iterator - Iterates through the enumerators of this // enumeration. @@ -1873,6 +1938,32 @@ public: /// \brief Set the underlying integer type. void setIntegerType(QualType T) { IntegerType = T; } + /// \brief Returns the width in bits requred to store all the + /// non-negative enumerators of this enum. + unsigned getNumPositiveBits() const { + return NumPositiveBits; + } + void setNumPositiveBits(unsigned Num) { + NumPositiveBits = Num; + assert(NumPositiveBits == Num && "can't store this bitcount"); + } + + /// \brief Returns the width in bits requred to store all the + /// negative enumerators of this enum. These widths include + /// the rightmost leading 1; that is: + /// + /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS + /// ------------------------ ------- ----------------- + /// -1 1111111 1 + /// -10 1110110 5 + /// -101 1001011 8 + unsigned getNumNegativeBits() const { + return NumNegativeBits; + } + void setNumNegativeBits(unsigned Num) { + NumNegativeBits = Num; + } + /// \brief Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. @@ -1942,6 +2033,11 @@ public: AnonymousStructOrUnion = Anon; } + ValueDecl *getAnonymousStructOrUnionObject(); + const ValueDecl *getAnonymousStructOrUnionObject() const { + return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject(); + } + bool hasObjectMember() const { return HasObjectMember; } void setHasObjectMember (bool val) { HasObjectMember = val; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index a9b948eee546..c15aeef14ba6 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -76,6 +76,11 @@ public: #include "clang/AST/DeclNodes.def" }; + /// \brief A placeholder type used to construct an empty shell of a + /// decl-derived type that will be filled in later (e.g., by some + /// deserialization method). + struct EmptyShell { }; + /// IdentifierNamespace - The different namespaces in which /// declarations may appear. According to C99 6.2.3, there are /// four namespaces, labels, tags, members and ordinary diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index aa649c811115..c19c200f265d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1061,10 +1061,6 @@ class CXXBaseOrMemberInitializer { /// In above example, BaseOrMember holds the field decl. for anonymous union /// and AnonUnionMember holds field decl for au_i1. FieldDecl *AnonUnionMember; - - /// IsVirtual - If the initializer is a base initializer, this keeps track - /// of whether the base is virtual or not. - bool IsVirtual; /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1072,6 +1068,28 @@ class CXXBaseOrMemberInitializer { /// RParenLoc - Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; + /// IsVirtual - If the initializer is a base initializer, this keeps track + /// of whether the base is virtual or not. + bool IsVirtual : 1; + + /// IsWritten - Whether or not the initializer is explicitly written + /// in the sources. + bool IsWritten : 1; + /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this + /// number keeps track of the textual order of this initializer in the + /// original sources, counting from 0; otherwise, if IsWritten is false, + /// it stores the number of array index variables stored after this + /// object in memory. + unsigned SourceOrderOrNumArrayIndices : 14; + + CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices); + public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit @@ -1089,6 +1107,17 @@ public: Expr *Init, SourceLocation R); + /// \brief Creates a new member initializer that optionally contains + /// array indices used to describe an elementwise initialization. + static CXXBaseOrMemberInitializer *Create(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices); + /// \brief Destroy the base or member initializer. void Destroy(ASTContext &Context); @@ -1146,6 +1175,30 @@ public: /// \brief Determine the source range covering the entire initializer. SourceRange getSourceRange() const; + + /// isWritten - Returns true if this initializer is explicitly written + /// in the source code. + bool isWritten() const { return IsWritten; } + + /// \brief Return the source position of the initializer, counting from 0. + /// If the initializer was implicit, -1 is returned. + int getSourceOrder() const { + return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1; + } + + /// \brief Set the source order of this initializer. This method can only + /// be called once for each initializer; it cannot be called on an + /// initializer having a positive number of (implicit) array indices. + void setSourceOrder(int pos) { + assert(!IsWritten && + "calling twice setSourceOrder() on the same initializer"); + assert(SourceOrderOrNumArrayIndices == 0 && + "setSourceOrder() used when there are implicit array indices"); + assert(pos >= 0 && + "setSourceOrder() used to make an initializer implicit"); + IsWritten = true; + SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos); + } FieldDecl *getAnonUnionMember() const { return AnonUnionMember; @@ -1154,9 +1207,31 @@ public: AnonUnionMember = anonMember; } + SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } + /// \brief Determine the number of implicit array indices used while + /// described an array member initialization. + unsigned getNumArrayIndices() const { + return IsWritten ? 0 : SourceOrderOrNumArrayIndices; + } + + /// \brief Retrieve a particular array index variable used to + /// describe an array member initialization. + VarDecl *getArrayIndex(unsigned I) { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + return reinterpret_cast<VarDecl **>(this + 1)[I]; + } + const VarDecl *getArrayIndex(unsigned I) const { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + return reinterpret_cast<const VarDecl * const *>(this + 1)[I]; + } + void setArrayIndex(unsigned I, VarDecl *Index) { + assert(I < getNumArrayIndices() && "Out of bounds member array index"); + reinterpret_cast<VarDecl **>(this + 1)[I] = Index; + } + Expr *getInit() { return static_cast<Expr *>(Init); } }; @@ -1201,6 +1276,7 @@ class CXXConstructorDecl : public CXXMethodDecl { virtual void Destroy(ASTContext& C); public: + static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -1343,6 +1419,7 @@ class CXXDestructorDecl : public CXXMethodDecl { } public: + static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, @@ -1398,6 +1475,7 @@ class CXXConversionDecl : public CXXMethodDecl { IsExplicitSpecified(isExplicitSpecified) { } public: + static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -1438,8 +1516,10 @@ public: /// ASTs and cannot be changed without altering that abi. To help /// ensure a stable abi for this, we choose the DW_LANG_ encodings /// from the dwarf standard. - enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002, - lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 }; + enum LanguageIDs { + lang_c = /* DW_LANG_C */ 0x0002, + lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 + }; private: /// Language - The language for this linkage specification. LanguageIDs Language; @@ -1457,12 +1537,20 @@ public: SourceLocation L, LanguageIDs Lang, bool Braces); + /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } - /// hasBraces - Determines whether this linkage specification had - /// braces in its syntactic form. + /// \brief Set the language specified by this linkage specification. + void setLanguage(LanguageIDs L) { Language = L; } + + /// \brief Determines whether this linkage specification had braces in + /// its syntactic form. bool hasBraces() const { return HadBraces; } + /// \brief Set whether this linkage specification has braces in its + /// syntactic form. + void setHasBraces(bool B) { HadBraces = B; } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LinkageSpecDecl *D) { return true; } static bool classofKind(Kind K) { return K == LinkageSpec; } @@ -1528,13 +1616,21 @@ class UsingDirectiveDecl : public NamedDecl { public: /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifiers the namespace name. + /// that qualifies the namespace name. SourceRange getQualifierRange() const { return QualifierRange; } + /// \brief Set the source range of the nested-name-specifier that + /// qualifies the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } + /// \brief Set the nested-name-specifier that qualifes the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } const NamedDecl *getNominatedNamespaceAsWritten() const { return NominatedNamespace; @@ -1547,17 +1643,32 @@ public: return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); } - /// getCommonAncestor - returns common ancestor context of using-directive, - /// and nominated by it namespace. + /// setNominatedNamespace - Set the namespace nominataed by the + /// using-directive. + void setNominatedNamespace(NamedDecl* NS); + + /// \brief Returns the common ancestor context of this using-directive and + /// its nominated namespace. DeclContext *getCommonAncestor() { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; } + /// \brief Set the common ancestor context of this using-directive and its + /// nominated namespace. + void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; } + + // FIXME: Could omit 'Key' in name. /// getNamespaceKeyLocation - Returns location of namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } + /// setNamespaceKeyLocation - Set the the location of the namespacekeyword. + void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; } + /// getIdentLocation - Returns location of identifier. SourceLocation getIdentLocation() const { return IdentLoc; } + /// setIdentLocation - set the location of the identifier. + void setIdentLocation(SourceLocation L) { IdentLoc = L; } + static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation NamespaceLoc, @@ -1591,7 +1702,7 @@ class NamespaceAliasDecl : public NamedDecl { /// name, if any. NestedNameSpecifier *Qualifier; - /// IdentLoc - Location of namespace identifier. + /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. SourceLocation IdentLoc; /// Namespace - The Decl that this alias points to. Can either be a @@ -1612,10 +1723,19 @@ public: /// that qualifiers the namespace name. SourceRange getQualifierRange() const { return QualifierRange; } + /// \brief Set the source range of the nested-name-specifier that qualifies + /// the namespace name. + void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } + /// \brief Set the nested-name-specifier that qualifies the name of the + /// namespace. + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + + /// \brief Retrieve the namespace declaration aliased by this directive. NamespaceDecl *getNamespace() { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) return AD->getNamespace(); @@ -1631,16 +1751,31 @@ public: /// "namespace foo = ns::bar;". SourceLocation getAliasLoc() const { return AliasLoc; } + /// Set the location o;f the alias name, e.e., 'foo' in + /// "namespace foo = ns::bar;". + void setAliasLoc(SourceLocation L) { AliasLoc = L; } + /// Returns the location of the 'namespace' keyword. SourceLocation getNamespaceLoc() const { return getLocation(); } /// Returns the location of the identifier in the named namespace. SourceLocation getTargetNameLoc() const { return IdentLoc; } + /// Set the location of the identifier in the named namespace. + void setTargetNameLoc(SourceLocation L) { IdentLoc = L; } + /// \brief Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } + /// \brief Set the namespace or namespace alias pointed to by this + /// alias decl. + void setAliasedNamespace(NamedDecl *ND) { + assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) && + "expecting namespace or namespace alias decl"); + Namespace = ND; + } + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation AliasLoc, IdentifierInfo *Alias, @@ -1687,16 +1822,20 @@ public: return new (C) UsingShadowDecl(DC, Loc, Using, Target); } - /// Gets the underlying declaration which has been brought into the + /// \brief Gets the underlying declaration which has been brought into the /// local scope. - NamedDecl *getTargetDecl() const { - return Underlying; - } + NamedDecl *getTargetDecl() const { return Underlying; } - /// Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const { - return Using; - } + /// \brief Sets the underlying declaration which has been brought into the + /// local scope. + void setTargetDecl(NamedDecl* ND) { Underlying = ND; } + + /// \brief Gets the using declaration to which this declaration is tied. + UsingDecl *getUsingDecl() const { return Using; } + + /// \brief Sets the using declaration that introduces this target + /// declaration. + void setUsingDecl(UsingDecl* UD) { Using = UD; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingShadowDecl *D) { return true; } @@ -1733,21 +1872,39 @@ class UsingDecl : public NamedDecl { } public: + // FIXME: Should be const? /// \brief Returns the source range that covers the nested-name-specifier /// preceding the namespace name. SourceRange getNestedNameRange() { return NestedNameRange; } - /// \brief Returns the source location of the "using" location itself. + /// \brief Set the source range of the nested-name-specifier. + void setNestedNameRange(SourceRange R) { NestedNameRange = R; } + + // FIXME; Should be const? + // FIXME: Naming is inconsistent with other get*Loc functions. + /// \brief Returns the source location of the "using" keyword. SourceLocation getUsingLocation() { return UsingLocation; } - /// \brief Get target nested name declaration. + /// \brief Set the source location of the 'using' keyword. + void setUsingLocation(SourceLocation L) { UsingLocation = L; } + + + /// \brief Get the target nested name declaration. NestedNameSpecifier* getTargetNestedNameDecl() { return TargetNestedName; } - /// isTypeName - Return true if using decl has 'typename'. + /// \brief Set the target nested name declaration. + void setTargetNestedNameDecl(NestedNameSpecifier *NNS) { + TargetNestedName = NNS; + } + + /// \brief Return true if the using declaration has 'typename'. bool isTypeName() const { return IsTypeName; } + /// \brief Sets whether the using declaration has 'typename'. + void setTypeName(bool TN) { IsTypeName = TN; } + typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator; shadow_iterator shadow_begin() const { return Shadows.begin(); } shadow_iterator shadow_end() const { return Shadows.end(); } @@ -1765,6 +1922,12 @@ public: } } + /// \brief Return the number of shadowed declarations associated with this + /// using declaration. + unsigned getNumShadowDecls() const { + return Shadows.size(); + } + static UsingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); @@ -1807,14 +1970,26 @@ public: /// preceding the namespace name. SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameSpecifier() { return TargetNestedNameSpecifier; } + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, @@ -1861,17 +2036,32 @@ public: /// preceding the namespace name. SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } + /// \brief Set the source range coverting the nested-name-specifier preceding + /// the namespace name. + void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } + /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameSpecifier() { return TargetNestedNameSpecifier; } + /// \brief Set the nested name declaration. + void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { + TargetNestedNameSpecifier = NNS; + } + /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } + /// \brief Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } + /// \brief Set the source location of the 'typename' keyword. + void setTypenameLoc(SourceLocation L) { TypenameLocation = L; } + static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 2a4b12ac2eaf..9602b677fca5 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -156,7 +156,8 @@ public: /// represents. DeclContext::lookup_result getLookupResult(ASTContext &Context) { if (isNull()) - return DeclContext::lookup_result(0, 0); + return DeclContext::lookup_result(DeclContext::lookup_iterator(0), + DeclContext::lookup_iterator(0)); if (hasDeclarationIDs()) materializeDecls(Context); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e34ec9ffcdf0..97d165696aad 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1421,13 +1421,21 @@ private: /// Null for @dynamic. Required for @synthesize. ObjCIvarDecl *PropertyIvarDecl; + + /// Null for @dynamic. Non-null if property must be copy-constructed in getter + Expr *GetterCXXConstructor; + + /// Null for @dynamic. Non-null if property has assignment operator to call + /// in Setter synthesis. + Expr *SetterCXXAssignment; ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, ObjCIvarDecl *ivarDecl) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - PropertyDecl(property), PropertyIvarDecl(ivarDecl) { + PropertyDecl(property), PropertyIvarDecl(ivarDecl), + GetterCXXConstructor(0), SetterCXXAssignment(0) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -1457,7 +1465,21 @@ public: return PropertyIvarDecl; } void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + + Expr *getGetterCXXConstructor() const { + return GetterCXXConstructor; + } + void setGetterCXXConstructor(Expr *getterCXXConstructor) { + GetterCXXConstructor = getterCXXConstructor; + } + Expr *getSetterCXXAssignment() const { + return SetterCXXAssignment; + } + void setSetterCXXAssignment(Expr *setterCXXAssignment) { + SetterCXXAssignment = setterCXXAssignment; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCPropertyImplDecl *D) { return true; } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 1ec38bacb51f..b7b90b14adfd 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -112,7 +112,7 @@ class TemplateArgumentListBuilder { unsigned MaxStructuredArgs; unsigned NumStructuredArgs; - TemplateArgument *FlatArgs; + llvm::SmallVector<TemplateArgument, 4> FlatArgs; unsigned MaxFlatArgs; unsigned NumFlatArgs; @@ -127,18 +127,12 @@ public: MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), AddingToPack(false), PackBeginIndex(0) { } - void Append(const TemplateArgument& Arg); + void Append(const TemplateArgument &Arg); void BeginPack(); void EndPack(); - void ReleaseArgs(); - - unsigned flatSize() const { - return NumFlatArgs; - } - const TemplateArgument *getFlatArguments() const { - return FlatArgs; - } + unsigned flatSize() const { return FlatArgs.size(); } + const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); } unsigned structuredSize() const { // If we don't have any structured args, just reuse the flat size. @@ -165,7 +159,7 @@ class TemplateArgumentList { /// \brief The template argument list. /// /// The integer value will be non-zero to indicate that this - /// template argument list does not own the pointer. + /// template argument list does own the pointer. llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; /// \brief The number of template arguments in this template @@ -175,14 +169,28 @@ class TemplateArgumentList { llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; unsigned NumStructuredArguments; + TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL + void operator=(const TemplateArgumentList &Other); // DO NOT IMPL public: + /// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs' + /// it copies them into a locally new[]'d array. If passed "false", then it + /// just references the array passed in. This is only safe if the builder + /// outlives it, but saves a copy. TemplateArgumentList(ASTContext &Context, TemplateArgumentListBuilder &Builder, bool TakeArgs); - /// \brief Produces a shallow copy of the given template argument list - TemplateArgumentList(const TemplateArgumentList &Other); + /// Produces a shallow copy of the given template argument list. This + /// assumes that the input argument list outlives it. This takes the list as + /// a pointer to avoid looking like a copy constructor, since this really + /// really isn't safe to use that way. + explicit TemplateArgumentList(const TemplateArgumentList *Other); + /// Used to release the memory associated with a TemplateArgumentList + /// object. FIXME: This is currently not called anywhere, but the + /// memory will still be freed when using a BumpPtrAllocator. + void Destroy(ASTContext &C); + ~TemplateArgumentList(); /// \brief Retrieve the template argument at a given index. @@ -280,6 +288,9 @@ public: /// specialization from the function template. const TemplateArgumentList *TemplateArguments; + /// \brief The template arguments as written in the sources, if provided. + const TemplateArgumentListInfo *TemplateArgumentsAsWritten; + /// \brief The point at which this function template specialization was /// first instantiated. SourceLocation PointOfInstantiation; @@ -454,6 +465,8 @@ public: /// Declaration of a template function. class FunctionTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + protected: /// \brief Data that is common to all of the declarations of a given /// function template. @@ -862,7 +875,7 @@ class ClassTemplateSpecializationDecl unsigned SpecializationKind : 3; protected: - ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, + ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -870,7 +883,7 @@ protected: public: static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl); @@ -1024,7 +1037,7 @@ class ClassTemplatePartialSpecializationDecl llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> InstantiatedFromMember; - ClassTemplatePartialSpecializationDecl(ASTContext &Context, + ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, @@ -1035,7 +1048,7 @@ class ClassTemplatePartialSpecializationDecl unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, - DC, L, SpecializedTemplate, Builder, + TK, DC, L, SpecializedTemplate, Builder, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), @@ -1043,7 +1056,7 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -1158,6 +1171,8 @@ public: /// Declaration of a class template. class ClassTemplateDecl : public TemplateDecl { + static void DeallocateCommon(void *Ptr); + protected: /// \brief Data that is common to all of the declarations of a given /// class template. diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 94017865d4c6..8a771d513c42 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -314,15 +314,16 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { /// retrieved using its member functions (e.g., /// getCXXConstructorName). class DeclarationNameTable { + ASTContext &Ctx; void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * CXXOperatorIdName *CXXOperatorNames; // Operator names - void *CXXLiteralOperatorNames; // Actually a FoldingSet<...> * + void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE public: - DeclarationNameTable(); + DeclarationNameTable(ASTContext &C); ~DeclarationNameTable(); /// getIdentifier - Create a declaration name that is a simple diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2946e464a7cf..66639e2ef733 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -51,6 +51,7 @@ typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; class Expr : public Stmt { QualType TR; + virtual void ANCHOR(); // key function. protected: /// TypeDependent - Whether this expression is type-dependent /// (C++ [temp.dep.expr]). @@ -247,6 +248,15 @@ public: SourceLocation DiagLoc; EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} + + // isGlobalLValue - Return true if the evaluated lvalue expression + // is global. + bool isGlobalLValue() const; + // hasSideEffects - Return true if the evaluated expression has + // side effects. + bool hasSideEffects() const { + return HasSideEffects; + } }; /// Evaluate - Return true if this is a constant which we can fold using @@ -255,10 +265,6 @@ 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; - /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we we can fold and convert to a boolean condition using /// any crazy technique that we want to. @@ -282,8 +288,7 @@ public: /// with link time known address. bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const; - /// EvaluateAsAnyLValue - The same as EvaluateAsLValue, except that it - /// also succeeds on stack based, immutable address lvalues. + /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const; /// \brief Enumeration used to describe how \c isNullPointerConstant() @@ -321,6 +326,10 @@ public: /// or CastExprs, returning their operand. Expr *IgnoreParenCasts(); + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any + /// ParenExpr or ImplicitCastExprs, returning their operand. + Expr *IgnoreParenImpCasts(); + /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. @@ -1468,13 +1477,10 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == CallExprClass || - T->getStmtClass() == CXXOperatorCallExprClass || - T->getStmtClass() == CXXMemberCallExprClass; + return T->getStmtClass() >= firstCallExprConstant && + T->getStmtClass() <= lastCallExprConstant; } static bool classof(const CallExpr *) { return true; } - static bool classof(const CXXOperatorCallExpr *) { return true; } - static bool classof(const CXXMemberCallExpr *) { return true; } // Iterators virtual child_iterator child_begin(); @@ -1933,14 +1939,8 @@ public: const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } static bool classof(const Stmt *T) { - StmtClass SC = T->getStmtClass(); - if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) - return true; - - if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass) - return true; - - return false; + return T->getStmtClass() >= firstCastExprConstant && + T->getStmtClass() <= lastCastExprConstant; } static bool classof(const CastExpr *) { return true; } @@ -2037,13 +2037,8 @@ public: QualType getTypeAsWritten() const { return TInfo->getType(); } static bool classof(const Stmt *T) { - StmtClass SC = T->getStmtClass(); - if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass) - return true; - if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) - return true; - - return false; + return T->getStmtClass() >= firstExplicitCastExprConstant && + T->getStmtClass() <= lastExplicitCastExprConstant; } static bool classof(const ExplicitCastExpr *) { return true; } }; @@ -2198,8 +2193,8 @@ public: bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } static bool classof(const Stmt *S) { - return S->getStmtClass() == BinaryOperatorClass || - S->getStmtClass() == CompoundAssignOperatorClass; + return S->getStmtClass() >= firstBinaryOperatorConstant && + S->getStmtClass() <= lastBinaryOperatorConstant; } static bool classof(const BinaryOperator *) { return true; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f9ca78ad292d..0c493f36df09 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -88,10 +88,13 @@ public: /// the object argument). class CXXMemberCallExpr : public CallExpr { public: - CXXMemberCallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, + CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs, QualType t, SourceLocation rparenloc) : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {} + CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) + : CallExpr(C, CXXMemberCallExprClass, Empty) { } + /// getImplicitObjectArgument - Retrieves the implicit object /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". @@ -318,6 +321,14 @@ public: Operand->isTypeDependent() || Operand->isValueDependent()), Operand(Operand), Range(R) { } + CXXTypeidExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXTypeidExprClass, Empty) { + if (isExpr) + Operand = (Expr*)0; + else + Operand = (TypeSourceInfo*)0; + } + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } /// \brief Retrieves the type operand of this typeid() expression after @@ -329,15 +340,25 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); return Operand.get<TypeSourceInfo *>(); } + + void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + Operand = TSI; + } - Expr* getExprOperand() const { + Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - - virtual SourceRange getSourceRange() const { - return Range; + + void setExprOperand(Expr *E) { + assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); + Operand = E; } + + virtual SourceRange getSourceRange() const { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTypeidExprClass; } @@ -371,6 +392,11 @@ public: Type->isDependentType(), Type->isDependentType()), Loc(L), Implicit(isImplicit) { } + CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } bool isImplicit() const { return Implicit; } @@ -399,6 +425,8 @@ public: // can by null, if the optional expression to throw isn't present. CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) : Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {} + CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} + const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } Expr *getSubExpr() { return cast_or_null<Expr>(Op); } void setSubExpr(Expr *E) { Op = E; } @@ -448,8 +476,7 @@ protected: CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, Expr *SubExpr) - : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) - { + : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) { *reinterpret_cast<Expr **>(this + 1) = SubExpr; } @@ -457,6 +484,9 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} + + // Param is the parameter whose default argument is used by this // expression. static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, @@ -475,6 +505,9 @@ public: const ParmVarDecl *getParam() const { return Param.getPointer(); } ParmVarDecl *getParam() { return Param.getPointer(); } + /// isExprStored - Return true if this expression owns the expression. + bool isExprStored() const { return Param.getInt(); } + // Retrieve the actual argument to the function call. const Expr *getExpr() const { if (Param.getInt()) @@ -486,10 +519,16 @@ public: return *reinterpret_cast<Expr **> (this + 1); return getParam()->getDefaultArg(); } + + void setExpr(Expr *E) { + Param.setInt(true); + Param.setPointer((ParmVarDecl*)E); + } /// \brief Retrieve the location where this default argument was actually /// used. SourceLocation getUsedLocation() const { return Loc; } + void setUsedLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { // Default argument expressions have no representation in the @@ -525,8 +564,20 @@ public: const CXXDestructorDecl *getDestructor() const { return Destructor; } }; -/// CXXBindTemporaryExpr - Represents binding an expression to a temporary, -/// so its destructor can be called later. +/// \brief Represents binding an expression to a temporary. +/// +/// This ensures the destructor is called for the temporary. It should only be +/// needed for non-POD, non-trivially destructable class types. For example: +/// +/// \code +/// struct S { +/// S() { } // User defined constructor makes S non-POD. +/// ~S() { } // User defined destructor makes it non-trivial. +/// }; +/// void test() { +/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. +/// } +/// \endcode class CXXBindTemporaryExpr : public Expr { CXXTemporary *Temp; @@ -541,11 +592,15 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXBindTemporaryExpr(EmptyShell Empty) + : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); CXXTemporary *getTemporary() { return Temp; } const CXXTemporary *getTemporary() const { return Temp; } + void setTemporary(CXXTemporary *T) { Temp = T; } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } Expr *getSubExpr() { return cast<Expr>(SubExpr); } @@ -572,8 +627,8 @@ public: /// const int &i = 10; /// /// a bind reference expression is inserted to indicate that 10 is bound to -/// a reference. (Ans also that a temporary needs to be created to hold the -/// value). +/// a reference, and that a temporary needs to be created to hold the +/// value. class CXXBindReferenceExpr : public Expr { // SubExpr - The expression being bound. Stmt *SubExpr; @@ -827,10 +882,15 @@ public: SourceLocation rParenLoc ) : Expr(CXXZeroInitValueExprClass, ty, false, false), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + explicit CXXZeroInitValueExpr(EmptyShell Shell) + : Expr(CXXZeroInitValueExprClass, Shell) { } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } + void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + /// @brief Whether this initialization expression was /// implicitly-generated. bool isImplicit() const { @@ -891,6 +951,11 @@ public: Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, SourceLocation startLoc, SourceLocation endLoc); + explicit CXXNewExpr(EmptyShell Shell) + : Expr(CXXNewExprClass, Shell), SubExprs(0) { } + + void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, + unsigned numConsArgs); virtual void DoDestroy(ASTContext &C); @@ -900,8 +965,11 @@ public: } FunctionDecl *getOperatorNew() const { return OperatorNew; } + void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } CXXConstructorDecl *getConstructor() const { return Constructor; } + void setConstructor(CXXConstructorDecl *D) { Constructor = D; } bool isArray() const { return Array; } Expr *getArraySize() { @@ -922,8 +990,11 @@ public: } bool isGlobalNew() const { return GlobalNew; } + void setGlobalNew(bool V) { GlobalNew = V; } bool isParenTypeId() const { return ParenTypeId; } + void setParenTypeId(bool V) { ParenTypeId = V; } bool hasInitializer() const { return Initializer; } + void setHasInitializer(bool V) { Initializer = V; } unsigned getNumConstructorArgs() const { return NumConstructorArgs; } Expr *getConstructorArg(unsigned i) { @@ -963,7 +1034,21 @@ public: const_arg_iterator constructor_arg_end() const { return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); } + + typedef Stmt **raw_arg_iterator; + raw_arg_iterator raw_arg_begin() { return SubExprs; } + raw_arg_iterator raw_arg_end() { + return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + } + const_arg_iterator raw_arg_begin() const { return SubExprs; } + const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } + + SourceLocation getStartLoc() const { return StartLoc; } + void setStartLoc(SourceLocation L) { StartLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + virtual SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } @@ -1260,7 +1345,9 @@ class OverloadExpr : public Expr { /// The results. These are undesugared, which is to say, they may /// include UsingShadowDecls. Access is relative to the naming /// class. - UnresolvedSet<4> Results; + // FIXME: Allocate this data after the OverloadExpr subclass. + DeclAccessPair *Results; + unsigned NumResults; /// The common name of these declarations. DeclarationName Name; @@ -1278,14 +1365,11 @@ class OverloadExpr : public Expr { bool HasExplicitTemplateArgs; protected: - OverloadExpr(StmtClass K, QualType T, bool Dependent, + OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool HasTemplateArgs) - : Expr(K, T, Dependent, Dependent), - Name(Name), Qualifier(Qualifier), QualifierRange(QRange), - NameLoc(NameLoc), HasExplicitTemplateArgs(HasTemplateArgs) - {} + bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); public: /// Computes whether an unresolved lookup on the given declarations @@ -1309,22 +1393,17 @@ public: return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); } - void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) { - Results.append(Begin, End); - } - /// Gets the naming class of this lookup, if any. CXXRecordDecl *getNamingClass() const; typedef UnresolvedSetImpl::iterator decls_iterator; - decls_iterator decls_begin() const { return Results.begin(); } - decls_iterator decls_end() const { return Results.end(); } - - /// Gets the decls as an unresolved set. - const UnresolvedSetImpl &getDecls() { return Results; } + decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } + decls_iterator decls_end() const { + return UnresolvedSetIterator(Results + NumResults); + } /// Gets the number of declarations in the unresolved set. - unsigned getNumDecls() const { return Results.size(); } + unsigned getNumDecls() const { return NumResults; } /// Gets the name looked up. DeclarationName getName() const { return Name; } @@ -1390,12 +1469,14 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass, + UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, + CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, - bool RequiresADL, bool Overloaded, bool HasTemplateArgs) - : OverloadExpr(UnresolvedLookupExprClass, T, Dependent, Qualifier, QRange, - Name, NameLoc, HasTemplateArgs), + bool RequiresADL, bool Overloaded, bool HasTemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End) + : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, + QRange, Name, NameLoc, HasTemplateArgs, Begin, End), RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} @@ -1407,11 +1488,15 @@ public: SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, - bool ADL, bool Overloaded) { - return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + bool ADL, bool Overloaded, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + return new(C) UnresolvedLookupExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, Dependent, NamingClass, Qualifier, QualifierRange, - Name, NameLoc, ADL, Overloaded, false); + Name, NameLoc, ADL, Overloaded, false, + Begin, End); } static UnresolvedLookupExpr *Create(ASTContext &C, @@ -1422,7 +1507,9 @@ public: DeclarationName Name, SourceLocation NameLoc, bool ADL, - const TemplateArgumentListInfo &Args); + const TemplateArgumentListInfo &Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End); /// True if this declaration should be extended by /// argument-dependent lookup. @@ -1611,7 +1698,7 @@ class CXXExprWithTemporaries : public Expr { CXXTemporary **Temps; unsigned NumTemps; - CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps, + CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); ~CXXExprWithTemporaries(); @@ -1619,11 +1706,17 @@ protected: virtual void DoDestroy(ASTContext &C); public: + CXXExprWithTemporaries(EmptyShell Empty) + : Expr(CXXExprWithTemporariesClass, Empty), + SubExpr(0), Temps(0), NumTemps(0) {} + static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps); unsigned getNumTemporaries() const { return NumTemps; } + void setNumTemporaries(ASTContext &C, unsigned N); + CXXTemporary *getTemporary(unsigned i) { assert(i < NumTemps && "Index out of range"); return Temps[i]; @@ -1631,6 +1724,10 @@ public: const CXXTemporary *getTemporary(unsigned i) const { return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i); } + void setTemporary(unsigned i, CXXTemporary *T) { + assert(i < NumTemps && "Index out of range"); + Temps[i] = T; + } Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } @@ -2020,7 +2117,7 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(QualType T, bool Dependent, + UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -2028,7 +2125,8 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceRange QualifierRange, DeclarationName Member, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); public: static UnresolvedMemberExpr * @@ -2039,7 +2137,8 @@ public: SourceRange QualifierRange, DeclarationName Member, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile new file mode 100644 index 000000000000..a25977cad621 --- /dev/null +++ b/include/clang/AST/Makefile @@ -0,0 +1,13 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = StmtNodes.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +INPUT_TDS = $(PROJ_SRC_DIR)/StmtNodes.td + +$(ObjDir)/StmtNodes.inc.tmp : StmtNodes.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang statement node tables with tblgen" + $(Verb) $(TableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< + diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index e78476ef51bb..2b3229e8fae9 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -109,6 +109,11 @@ private: /// which is the alignment of the object without virtual bases. uint64_t NonVirtualAlign; + /// SizeOfLargestEmptySubobject - The size of the largest empty subobject + /// (either a base or a member). Will be zero if the class doesn't contain + /// any empty subobjects. + uint64_t SizeOfLargestEmptySubobject; + /// PrimaryBase - The primary base info for this record. PrimaryBaseInfo PrimaryBase; @@ -127,7 +132,6 @@ private: CXXRecordLayoutInfo *CXXInfo; friend class ASTContext; - friend class ASTRecordLayoutBuilder; ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment, unsigned datasize, const uint64_t *fieldoffsets, @@ -139,7 +143,9 @@ private: uint64_t size, unsigned alignment, uint64_t datasize, const uint64_t *fieldoffsets, unsigned fieldcount, uint64_t nonvirtualsize, unsigned nonvirtualalign, - const PrimaryBaseInfo &PrimaryBase, + uint64_t SizeOfLargestEmptySubobject, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseIsVirtual, const BaseOffsetsMapTy& BaseOffsets, const BaseOffsetsMapTy& VBaseOffsets); @@ -222,6 +228,11 @@ public: return CXXInfo->VBaseOffsets[VBase]; } + uint64_t getSizeOfLargestEmptySubobject() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->SizeOfLargestEmptySubobject; + } + primary_base_info_iterator primary_base_begin() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h new file mode 100644 index 000000000000..07865e0eb3f1 --- /dev/null +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -0,0 +1,768 @@ +//===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- 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 the RecursiveASTVisitor interface, which recursively +// traverses the entire AST. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" + +namespace clang { + +#define DISPATCH(NAME, CLASS, Var) \ +return getDerived().Visit ## NAME(static_cast<CLASS*>(Var)) + +// We use preprocessor meta-programming to generate the Visit*() +// methods for all subclasses of Stmt, Decl, and Type. Some of the +// generated definitions, however, need to be customized. The +// meta-programming technique we use doesn't let us select which +// methods to generate. Therefore we have to generate ALL of them in +// a helper class RecursiveASTVisitorImpl, and override the ones we +// don't like in a child class RecursiveASTVisitor (C++ doesn't allow +// overriding a method in the same class). +// +// Do not use this class directly - use RecursiveASTVisitor instead. +template<typename Derived> +class RecursiveASTVisitorImpl { +public: + /// \brief Return a reference to the derived class. + Derived &getDerived() { return *static_cast<Derived*>(this); } + + /// \brief Recursively visit a statement or expression, by + /// dispatching to Visit*() based on the argument's dynamic type. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Stmt *S); + + /// \brief Recursively visit a type, by dispatching to + /// Visit*Type() based on the argument's getTypeClass() property. + /// This is NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is a Null type). + bool Visit(QualType T); + + /// \brief Recursively visit a declaration, by dispatching to + /// Visit*Decl() based on the argument's dynamic type. This is + /// NOT meant to be overridden by a subclass. + /// + /// \returns true if the visitation was terminated early, false + /// otherwise (including when the argument is NULL). + bool Visit(Decl *D); + + /// \brief Recursively visit a C++ nested-name-specifier. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + + /// \brief Recursively visit a template name. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateName(TemplateName Template); + + /// \brief Recursively visit a template argument. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArgument(const TemplateArgument &Arg); + + /// \brief Recursively visit a set of template arguments. + /// + /// \returns true if the visitation was terminated early, false otherwise. + bool VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + + // If the implementation chooses not to implement a certain visit method, fall + // back on VisitExpr or whatever else is the superclass. +#define STMT(CLASS, PARENT) \ +bool Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT, S); } +#include "clang/AST/StmtNodes.inc" + + // If the implementation doesn't implement binary operator methods, fall back + // on VisitBinaryOperator. +#define BINOP_FALLBACK(NAME) \ +bool VisitBin ## NAME(BinaryOperator *S) { \ +DISPATCH(BinaryOperator, BinaryOperator, S); \ +} + BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) + BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) + BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) + BINOP_FALLBACK(Shr) + + BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) + BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) + BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) + BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) + + BINOP_FALLBACK(Assign) + BINOP_FALLBACK(Comma) +#undef BINOP_FALLBACK + + // If the implementation doesn't implement compound assignment operator + // methods, fall back on VisitCompoundAssignOperator. +#define CAO_FALLBACK(NAME) \ +bool VisitBin ## NAME(CompoundAssignOperator *S) { \ +DISPATCH(CompoundAssignOperator, CompoundAssignOperator, S); \ +} + CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) + CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) + CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) + CAO_FALLBACK(XorAssign) +#undef CAO_FALLBACK + + // If the implementation doesn't implement unary operator methods, fall back + // on VisitUnaryOperator. +#define UNARYOP_FALLBACK(NAME) \ +bool VisitUnary ## NAME(UnaryOperator *S) { \ +DISPATCH(UnaryOperator, UnaryOperator, S); \ +} + UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) + UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) + UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) + + UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) + UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) + UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) + UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) +#undef UNARYOP_FALLBACK + + /// \brief Basis for statement and expression visitation, which + /// visits all of the substatements and subexpressions. + /// + /// The relation between Visit(Stmt *S) and this method is that + /// the former dispatches to Visit*() based on S's dynamic type, + /// which forwards the call up the inheritance chain until + /// reaching VisitStmt(), which then calls Visit() on each + /// substatement/subexpression. + bool VisitStmt(Stmt *S); + + /// \brief Basis for type visitation, which by default does nothing. + /// + /// The relation between Visit(QualType T) and this method is + /// that the former dispatches to Visit*Type(), which forwards the + /// call up the inheritance chain until reaching VisitType(). + bool VisitType(Type *T); + +#define TYPE(Class, Base) \ + bool Visit##Class##Type(Class##Type *T); +#include "clang/AST/TypeNodes.def" + + /// \brief Basis for declaration and definition visitation, which + /// visits all of the subnodes. + /// + /// The relation between Visit(Decl *) and this method is that the + /// former dispatches to Visit*Decl(), which forwards the call up + /// the inheritance chain until reaching VisitDecl(). + bool VisitDecl(Decl *D); + +#define DECL(Class, Base) \ + bool Visit##Class##Decl(Class##Decl *D) { \ + return getDerived().Visit##Base(D); \ + } +#define ABSTRACT_DECL(Class, Base) DECL(Class, Base) +#include "clang/AST/DeclNodes.def" +}; + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Stmt *S) { + if (!S) + return false; + + // If we have a binary expr, dispatch to the subcode of the binop. A smart + // optimizer (e.g. LLVM) will fold this comparison into the switch stmt + // below. + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator, S); + case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator, S); + case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator, S); + case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator, S); + case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator, S); + case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator, S); + case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator, S); + case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator, S); + case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator, S); + + case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator, S); + case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator, S); + case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator, S); + case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator, S); + case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator, S); + case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator, S); + + case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator, S); + case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator, S); + case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator, S); + case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator, S); + case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator, S); + case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator, S); + case BinaryOperator::MulAssign: + DISPATCH(BinMulAssign, CompoundAssignOperator, S); + case BinaryOperator::DivAssign: + DISPATCH(BinDivAssign, CompoundAssignOperator, S); + case BinaryOperator::RemAssign: + DISPATCH(BinRemAssign, CompoundAssignOperator, S); + case BinaryOperator::AddAssign: + DISPATCH(BinAddAssign, CompoundAssignOperator, S); + case BinaryOperator::SubAssign: + DISPATCH(BinSubAssign, CompoundAssignOperator, S); + case BinaryOperator::ShlAssign: + DISPATCH(BinShlAssign, CompoundAssignOperator, S); + case BinaryOperator::ShrAssign: + DISPATCH(BinShrAssign, CompoundAssignOperator, S); + case BinaryOperator::AndAssign: + DISPATCH(BinAndAssign, CompoundAssignOperator, S); + case BinaryOperator::OrAssign: + DISPATCH(BinOrAssign, CompoundAssignOperator, S); + case BinaryOperator::XorAssign: + DISPATCH(BinXorAssign, CompoundAssignOperator, S); + case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator, S); + } + } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { + switch (UnOp->getOpcode()) { + case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator, S); + case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator, S); + case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator, S); + case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator, S); + case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator, S); + case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator, S); + case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator, S); + case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator, S); + case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator, S); + case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator, S); + case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator, S); + case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator, S); + case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator, S); + case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator, S); + } + } + + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ +case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S); +#include "clang/AST/StmtNodes.inc" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(QualType T) { + if (T.isNull()) + return false; + + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + case Type::Class: DISPATCH(Class##Type, Class##Type, T.getTypePtr()); +#include "clang/AST/TypeNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::Visit(Decl *D) { + if (!D) + return false; + + switch (D->getKind()) { +#define ABSTRACT_DECL(Class, Base) +#define DECL(Class, Base) \ + case Decl::Class: DISPATCH(Class##Decl, Class##Decl, D); +#include "clang/AST/DeclNodes.def" + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitNestedNameSpecifier( + NestedNameSpecifier *NNS) { + if (NNS->getPrefix() && + getDerived().VisitNestedNameSpecifier(NNS->getPrefix())) + return true; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::Global: + return false; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return Visit(QualType(NNS->getAsType(), 0)); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateName(TemplateName Template) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + return DTN->getQualifier() && + getDerived().VisitNestedNameSpecifier(DTN->getQualifier()); + + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + return getDerived().VisitNestedNameSpecifier(QTN->getQualifier()); + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArgument( + const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + return false; + + case TemplateArgument::Type: + return Visit(Arg.getAsType()); + + case TemplateArgument::Template: + return getDerived().VisitTemplateName(Arg.getAsTemplate()); + + case TemplateArgument::Expression: + return getDerived().Visit(Arg.getAsExpr()); + + case TemplateArgument::Pack: + return getDerived().VisitTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArguments( + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) + if (getDerived().VisitTemplateArgument(Args[I])) + return true; + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitStmt(Stmt *Node) { + for (Stmt::child_iterator C = Node->child_begin(), CEnd = Node->child_end(); + C != CEnd; ++C) { + if (Visit(*C)) + return true; + } + + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitType(Type *T) { + return false; +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBuiltinType(BuiltinType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitComplexType(ComplexType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitPointerType(PointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitBlockPointerType( + BlockPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitReferenceType(ReferenceType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitLValueReferenceType( + LValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRValueReferenceType( + RValueReferenceType *T) { + return getDerived().VisitReferenceType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitMemberPointerType( + MemberPointerType *T) { + if (Visit(QualType(T->getClass(), 0)) || Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitArrayType(ArrayType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitConstantArrayType( + ConstantArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitIncompleteArrayType( + IncompleteArrayType *T) { + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVariableArrayType( + VariableArrayType *T) { + if (Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedArrayType( + DependentSizedArrayType *T) { + if (T->getSizeExpr() && Visit(T->getSizeExpr())) + return true; + + return getDerived().VisitArrayType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedExtVectorType( + DependentSizedExtVectorType *T) { + if ((T->getSizeExpr() && Visit(T->getSizeExpr())) || + Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitVectorType(VectorType *T) { + if (Visit(T->getElementType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitExtVectorType(ExtVectorType *T) { + return getDerived().VisitVectorType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionType(FunctionType *T) { + if (Visit(T->getResultType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionNoProtoType( + FunctionNoProtoType *T) { + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitFunctionProtoType( + FunctionProtoType *T) { + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + if (Visit(*A)) + return true; + } + + for (FunctionProtoType::exception_iterator E = T->exception_begin(), + EEnd = T->exception_end(); + E != EEnd; ++E) { + if (Visit(*E)) + return true; + } + + return getDerived().VisitFunctionType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitUnresolvedUsingType( + UnresolvedUsingType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypedefType(TypedefType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfExprType(TypeOfExprType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfType(TypeOfType *T) { + if (Visit(T->getUnderlyingType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecltypeType(DecltypeType *T) { + if (Visit(T->getUnderlyingExpr())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTagType(TagType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitRecordType(RecordType *T) { + return getDerived().VisitTagType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitEnumType(EnumType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateTypeParmType( + TemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitSubstTemplateTypeParmType( + SubstTemplateTypeParmType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitTemplateSpecializationType( + TemplateSpecializationType *T) { + if (getDerived().VisitTemplateName(T->getTemplateName()) || + getDerived().VisitTemplateArguments(T->getArgs(), T->getNumArgs())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitInjectedClassNameType( + InjectedClassNameType *T) { + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitElaboratedType(ElaboratedType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + if (Visit(T->getNamedType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDependentNameType( + DependentNameType *T) { + if (T->getQualifier() && + getDerived().VisitNestedNameSpecifier(T->getQualifier())) + return true; + + if (T->getTemplateId() && + getDerived().VisitTemplateSpecializationType( + const_cast<TemplateSpecializationType *>(T->getTemplateId()))) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCInterfaceType( + ObjCInterfaceType *T) { + return getDerived().VisitObjCObjectType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectType(ObjCObjectType *T) { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + if (Visit(T->getBaseType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectPointerType( + ObjCObjectPointerType *T) { + if (Visit(T->getPointeeType())) + return true; + + return getDerived().VisitType(T); +} + +template<typename Derived> +bool RecursiveASTVisitorImpl<Derived>::VisitDecl(Decl *D) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) { + for (DeclContext::decl_iterator Child = DC->decls_begin(), + ChildEnd = DC->decls_end(); + Child != ChildEnd; ++Child) + if (Visit(*Child)) + return true; + + return false; + } + + return false; +} + +/// \brief A visitor that recursively walks the entire Clang AST. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously +/// recurring template pattern) and override any of the Visit* +/// methods (except Visit()) for declaration, type, statement, +/// expression, or other AST nodes where the visitor should customize +/// behavior. Returning "true" from one of these overridden functions +/// will abort the entire traversal. An overridden Visit* method +/// will not descend further into the AST for that node unless +/// Base::Visit* is called. +template<typename Derived> +class RecursiveASTVisitor : public RecursiveASTVisitorImpl<Derived> { + typedef RecursiveASTVisitorImpl<Derived> Impl; +public: + typedef RecursiveASTVisitor<Derived> Base; + + bool VisitDeclaratorDecl(DeclaratorDecl *D); + bool VisitFunctionDecl(FunctionDecl *D); + bool VisitVarDecl(VarDecl *D); + bool VisitBlockDecl(BlockDecl *D); + bool VisitDeclStmt(DeclStmt *S); + bool VisitFunctionType(FunctionType *F); + bool VisitFunctionProtoType(FunctionProtoType *F); +}; + +#define DEFINE_VISIT(Type, Name, Statement) \ + template<typename Derived> \ + bool RecursiveASTVisitor<Derived>::Visit ## Type (Type *Name) { \ + if (Impl::Visit ## Type (Name)) return true; \ + { Statement; } \ + return false; \ + } + +DEFINE_VISIT(DeclaratorDecl, D, { + if (TypeSourceInfo *TInfo = D->getTypeSourceInfo()) + return this->Visit(TInfo->getType()); + }) + +DEFINE_VISIT(FunctionDecl, D, { + if (D->isThisDeclarationADefinition()) + return this->Visit(D->getBody()); + }) + +DEFINE_VISIT(VarDecl, D, return this->Visit(D->getInit())) + +DEFINE_VISIT(BlockDecl, D, return this->Visit(D->getBody())) + +DEFINE_VISIT(DeclStmt, S, { + for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + if (this->Visit(*I)) + return true; + } + }) + +// FunctionType is the common base class of FunctionNoProtoType (a +// K&R-style function declaration that has no information about +// its arguments) and FunctionProtoType. +DEFINE_VISIT(FunctionType, F, return this->Visit(F->getResultType())) + +DEFINE_VISIT(FunctionProtoType, F, { + for (unsigned i = 0; i != F->getNumArgs(); ++i) { + if (this->Visit(F->getArgType(i))) + return true; + } + for (unsigned i = 0; i != F->getNumExceptions(); ++i) { + if (this->Visit(F->getExceptionType(i))) + return true; + } + }) + +#undef DEFINE_VISIT + +#undef DISPATCH + +} // end namespace clang + +#endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 0b68a4007363..9deae1561586 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -98,12 +98,14 @@ public: enum StmtClass { NoStmtClass = 0, #define STMT(CLASS, PARENT) CLASS##Class, -#define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class, -#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class, -#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class, -#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class -#define ABSTRACT_EXPR(CLASS, PARENT) -#include "clang/AST/StmtNodes.def" +#define STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class, +#define LAST_STMT_RANGE(BASE, FIRST, LAST) \ + first##BASE##Constant = FIRST##Class, \ + last##BASE##Constant = LAST##Class +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" }; private: /// \brief The statement class. @@ -1083,9 +1085,15 @@ public: class ReturnStmt : public Stmt { Stmt *RetExpr; SourceLocation RetLoc; + const VarDecl *NRVOCandidate; + public: - ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), - RetExpr((Stmt*) E), RetLoc(RL) {} + ReturnStmt(SourceLocation RL) + : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { } + + ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) + : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL), + NRVOCandidate(NRVOCandidate) {} /// \brief Build an empty return expression. explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } @@ -1097,6 +1105,14 @@ public: SourceLocation getReturnLoc() const { return RetLoc; } void setReturnLoc(SourceLocation L) { RetLoc = L; } + /// \brief Retrieve the variable that might be used for the named return + /// value optimization. + /// + /// The optimization itself can only be performed if the variable is + /// also marked as an NRVO object. + const VarDecl *getNRVOCandidate() const { return NRVOCandidate; } + void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } + virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { diff --git a/include/clang/AST/StmtNodes.td b/include/clang/AST/StmtNodes.td new file mode 100644 index 000000000000..60c94a609b4a --- /dev/null +++ b/include/clang/AST/StmtNodes.td @@ -0,0 +1,127 @@ +class Stmt<bit abstract = 0> { + bit Abstract = abstract; +} + +class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> { + Stmt Base = base; +} + +// Statements +def NullStmt : Stmt; +def CompoundStmt : Stmt; +def LabelStmt : Stmt; +def IfStmt : Stmt; +def SwitchStmt : Stmt; +def WhileStmt : Stmt; +def DoStmt : Stmt; +def ForStmt : Stmt; +def GotoStmt : Stmt; +def IndirectGotoStmt : Stmt; +def ContinueStmt : Stmt; +def BreakStmt : Stmt; +def ReturnStmt : Stmt; +def DeclStmt : Stmt; +def SwitchCase : Stmt; +def CaseStmt : DStmt<SwitchCase>; +def DefaultStmt : DStmt<SwitchCase>; + +// GNU Extensions +def AsmStmt : Stmt; + +// Obj-C statements +def ObjCAtTryStmt : Stmt; +def ObjCAtCatchStmt : Stmt; +def ObjCAtFinallyStmt : Stmt; +def ObjCAtThrowStmt : Stmt; +def ObjCAtSynchronizedStmt : Stmt; +def ObjCForCollectionStmt : Stmt; + +// C++ statments +def CXXCatchStmt : Stmt; +def CXXTryStmt : Stmt; + +// Expressions +def Expr : Stmt<1>; +def PredefinedExpr : DStmt<Expr>; +def DeclRefExpr : DStmt<Expr>; +def IntegerLiteral : DStmt<Expr>; +def FloatingLiteral : DStmt<Expr>; +def ImaginaryLiteral : DStmt<Expr>; +def StringLiteral : DStmt<Expr>; +def CharacterLiteral : DStmt<Expr>; +def ParenExpr : DStmt<Expr>; +def UnaryOperator : DStmt<Expr>; +def OffsetOfExpr : DStmt<Expr>; +def SizeOfAlignOfExpr : DStmt<Expr>; +def ArraySubscriptExpr : DStmt<Expr>; +def CallExpr : DStmt<Expr>; +def MemberExpr : DStmt<Expr>; +def CastExpr : DStmt<Expr, 1>; +def BinaryOperator : DStmt<Expr>; +def CompoundAssignOperator : DStmt<BinaryOperator>; +def ConditionalOperator : DStmt<Expr>; +def ImplicitCastExpr : DStmt<CastExpr>; +def ExplicitCastExpr : DStmt<CastExpr, 1>; +def CStyleCastExpr : DStmt<ExplicitCastExpr>; +def CompoundLiteralExpr : DStmt<Expr>; +def ExtVectorElementExpr : DStmt<Expr>; +def InitListExpr : DStmt<Expr>; +def DesignatedInitExpr : DStmt<Expr>; +def ImplicitValueInitExpr : DStmt<Expr>; +def ParenListExpr : DStmt<Expr>; +def VAArgExpr : DStmt<Expr>; + +// GNU Extensions. +def AddrLabelExpr : DStmt<Expr>; +def StmtExpr : DStmt<Expr>; +def TypesCompatibleExpr : DStmt<Expr>; +def ChooseExpr : DStmt<Expr>; +def GNUNullExpr : DStmt<Expr>; + +// C++ Expressions. +def CXXOperatorCallExpr : DStmt<CallExpr>; +def CXXMemberCallExpr : DStmt<CallExpr>; +def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>; +def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>; +def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>; +def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>; +def CXXConstCastExpr : DStmt<CXXNamedCastExpr>; +def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>; +def CXXTypeidExpr : DStmt<Expr>; +def CXXBoolLiteralExpr : DStmt<Expr>; +def CXXNullPtrLiteralExpr : DStmt<Expr>; +def CXXThisExpr : DStmt<Expr>; +def CXXThrowExpr : DStmt<Expr>; +def CXXDefaultArgExpr : DStmt<Expr>; +def CXXZeroInitValueExpr : DStmt<Expr>; +def CXXNewExpr : DStmt<Expr>; +def CXXDeleteExpr : DStmt<Expr>; +def CXXPseudoDestructorExpr : DStmt<Expr>; +def UnresolvedLookupExpr : DStmt<Expr>; +def UnaryTypeTraitExpr : DStmt<Expr>; +def DependentScopeDeclRefExpr : DStmt<Expr>; +def CXXConstructExpr : DStmt<Expr>; +def CXXBindTemporaryExpr : DStmt<Expr>; +def CXXBindReferenceExpr : DStmt<Expr>; +def CXXExprWithTemporaries : DStmt<Expr>; +def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; +def CXXUnresolvedConstructExpr : DStmt<Expr>; +def CXXDependentScopeMemberExpr : DStmt<Expr>; +def UnresolvedMemberExpr : DStmt<Expr>; + +// Obj-C Expressions. +def ObjCStringLiteral : DStmt<Expr>; +def ObjCEncodeExpr : DStmt<Expr>; +def ObjCMessageExpr : DStmt<Expr>; +def ObjCSelectorExpr : DStmt<Expr>; +def ObjCProtocolExpr : DStmt<Expr>; +def ObjCIvarRefExpr : DStmt<Expr>; +def ObjCPropertyRefExpr : DStmt<Expr>; +def ObjCImplicitSetterGetterRefExpr : DStmt<Expr>; +def ObjCSuperExpr : DStmt<Expr>; +def ObjCIsaExpr : DStmt<Expr>; + +// Clang Extensions. +def ShuffleVectorExpr : DStmt<Expr>; +def BlockExpr : DStmt<Expr>; +def BlockDeclRefExpr : DStmt<Expr>; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 4986f08ac124..8078451fa31f 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -105,10 +105,10 @@ public: // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. switch (S->getStmtClass()) { default: assert(0 && "Unknown stmt kind!"); -#define ABSTRACT_EXPR(CLASS, PARENT) +#define ABSTRACT_STMT(STMT) #define STMT(CLASS, PARENT) \ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); -#include "clang/AST/StmtNodes.def" +#include "clang/AST/StmtNodes.inc" } } @@ -116,7 +116,7 @@ public: // back on VisitExpr or whatever else is the superclass. #define STMT(CLASS, PARENT) \ RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); } -#include "clang/AST/StmtNodes.def" +#include "clang/AST/StmtNodes.inc" // If the implementation doesn't implement binary operator methods, fall back // on VisitBinaryOperator. diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 50a100c6af13..8b38001bd104 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -28,6 +28,7 @@ namespace llvm { namespace clang { class Decl; +class DiagnosticBuilder; class Expr; class TypeSourceInfo; @@ -473,6 +474,9 @@ public: } }; -} +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const TemplateArgument &Arg); + +} // end namespace clang #endif diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index f3de9fa011bc..2e3b6df0549b 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -188,7 +188,7 @@ const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, /// declaration for "vector". The QualifiedTemplateName class is only /// used to provide "sugar" for template names that were expressed /// with a qualified name, and has no semantic meaning. In this -/// manner, it is to TemplateName what QualifiedNameType is to Type, +/// manner, it is to TemplateName what ElaboratedType is to Type, /// providing extra syntactic sugar for downstream clients. class QualifiedTemplateName : public llvm::FoldingSetNode { /// \brief The nested name specifier that qualifies the template name. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 030c74c64089..c24bddb30082 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -92,7 +92,7 @@ namespace clang { class TemplateArgumentLoc; class TemplateArgumentListInfo; class Type; - class QualifiedNameType; + class ElaboratedType; struct PrintingPolicy; template <typename> class CanQual; @@ -396,7 +396,8 @@ enum CallingConv { CC_Default, CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall // __attribute__((fastcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall // __attribute__((thiscall)) }; @@ -755,6 +756,9 @@ public: }; private: + Type(const Type&); // DO NOT IMPLEMENT. + void operator=(const Type&); // DO NOT IMPLEMENT. + QualType CanonicalType; /// TypeClass bitfield - Enum that specifies what subclass this belongs to. @@ -764,15 +768,25 @@ private: /// Note that this should stay at the end of the ivars for Type so that /// subclasses can pack their bitfields into the same word. bool Dependent : 1; - - Type(const Type&); // DO NOT IMPLEMENT. - void operator=(const Type&); // DO NOT IMPLEMENT. + + /// \brief Whether the linkage of this type is already known. + mutable bool LinkageKnown : 1; + + /// \brief Linkage of this type. + mutable unsigned CachedLinkage : 2; + protected: + /// \brief Compute the linkage of this type. + virtual Linkage getLinkageImpl() const; + + enum { BitsRemainingInType = 20 }; + // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } Type(TypeClass tc, QualType Canonical, bool dependent) : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), - TC(tc), Dependent(dependent) {} + TC(tc), Dependent(dependent), LinkageKnown(false), + CachedLinkage(NoLinkage) {} virtual ~Type() {} virtual void Destroy(ASTContext& C); friend class ASTContext; @@ -879,7 +893,7 @@ public: bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. // FIXME: change this to 'raw' interface type, so we can used 'interface' type // for the common case. - bool isObjCInterfaceType() const; // NSString or NSString<foo> + bool isObjCObjectType() const; // NSString or typeof(*(id)0) bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedClassType() const; // Class<foo> @@ -920,7 +934,7 @@ public: // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; - const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; + const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; /// \brief Retrieves the CXXRecordDecl that this type refers to, either @@ -935,10 +949,6 @@ public: // immediately following this class. template <typename T> const T *getAs() const; - /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC - /// interface, return the interface type, otherwise return null. - const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const; - /// getArrayElementTypeNoTypeQual - If this is an array type, return the /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. @@ -977,10 +987,13 @@ public: /// set of type specifiers. bool isSpecifierType() const; - const char *getTypeClassName() const; - /// \brief Determine the linkage of this type. - virtual Linkage getLinkage() const; + Linkage getLinkage() const; + + /// \brief Note that the linkage is no longer known. + void ClearLinkageCache(); + + const char *getTypeClassName() const; QualType getCanonicalTypeInternal() const { return CanonicalType; @@ -1040,12 +1053,25 @@ public: UndeducedAuto, // In C++0x, this represents the type of an auto variable // that has not been deduced yet. - ObjCId, // This represents the ObjC 'id' type. - ObjCClass, // This represents the ObjC 'Class' type. + + /// The primitive Objective C 'id' type. The type pointed to by the + /// user-visible 'id' type. Only ever shows up in an AST as the base + /// type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The type pointed to by the + /// user-visible 'Class' type. Only ever shows up in an AST as the + /// base type of an ObjCObjectType. + ObjCClass, + ObjCSel // This represents the ObjC 'SEL' type. }; private: Kind TypeKind; + +protected: + virtual Linkage getLinkageImpl() const; + public: BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)), @@ -1073,8 +1099,6 @@ public: return TypeKind >= Float && TypeKind <= LongDouble; } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } static bool classof(const BuiltinType *) { return true; } }; @@ -1089,6 +1113,10 @@ class ComplexType : public Type, public llvm::FoldingSetNode { ElementType(Element) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } @@ -1102,8 +1130,6 @@ public: ID.AddPointer(Element.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Complex; } static bool classof(const ComplexType *) { return true; } }; @@ -1117,6 +1143,10 @@ class PointerType : public Type, public llvm::FoldingSetNode { Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getPointeeType() const { return PointeeType; } @@ -1131,8 +1161,6 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } static bool classof(const PointerType *) { return true; } }; @@ -1148,6 +1176,10 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: // Get the pointee type. Pointee is required to always be a function type. @@ -1163,8 +1195,6 @@ public: ID.AddPointer(Pointee.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == BlockPointer; } @@ -1200,6 +1230,9 @@ protected: PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), InnerRef(Referencee->isReferenceType()) { } + + virtual Linkage getLinkageImpl() const; + public: bool isSpelledAsLValue() const { return SpelledAsLValue; } bool isInnerRef() const { return InnerRef; } @@ -1223,8 +1256,6 @@ public: ID.AddBoolean(SpelledAsLValue); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == LValueReference || T->getTypeClass() == RValueReference; @@ -1281,6 +1312,10 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { PointeeType(Pointee), Class(Cls) { } friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: QualType getPointeeType() const { return PointeeType; } @@ -1299,8 +1334,6 @@ public: ID.AddPointer(Class); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } @@ -1342,6 +1375,9 @@ protected: ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {} friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } ArraySizeModifier getSizeModifier() const { @@ -1352,8 +1388,6 @@ public: } unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || T->getTypeClass() == VariableArray || @@ -1629,6 +1663,9 @@ protected: : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} friend class ASTContext; // ASTContext creates these. + + virtual Linkage getLinkageImpl() const; + public: QualType getElementType() const { return ElementType; } @@ -1655,8 +1692,6 @@ public: ID.AddBoolean(isPixel); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; } @@ -1733,6 +1768,8 @@ public: /// class of FunctionNoProtoType and FunctionProtoType. /// class FunctionType : public Type { + virtual void ANCHOR(); // Key function for FunctionType. + /// SubClassData - This field is owned by the subclass, put here to pack /// tightly with the ivars in Type. bool SubClassData : 1; @@ -1753,7 +1790,7 @@ class FunctionType : public Type { unsigned RegParm : 3; /// CallConv - The calling convention used by the function. - unsigned CallConv : 2; + unsigned CallConv : 3; // The type returned by the function. QualType ResultType; @@ -1821,7 +1858,7 @@ class FunctionType : public Type { // The value passed to __attribute__((regparm(x))) unsigned RegParm; // The calling convention as specified via - // __attribute__((cdecl|stdcall||fastcall)) + // __attribute__((cdecl|stdcall|fastcall|thiscall)) CallingConv CC; }; @@ -1862,6 +1899,10 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { : FunctionType(FunctionNoProto, Result, false, 0, Canonical, /*Dependent=*/false, Info) {} friend class ASTContext; // ASTContext creates these. + +protected: + virtual Linkage getLinkageImpl() const; + public: // No additional state past what FunctionType provides. @@ -1879,8 +1920,6 @@ public: ID.AddPointer(ResultType.getAsOpaquePtr()); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto; } @@ -1944,6 +1983,9 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. +protected: + virtual Linkage getLinkageImpl() const; + public: unsigned getNumArgs() const { return NumArgs; } QualType getArgType(unsigned i) const { @@ -1984,8 +2026,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; } @@ -2190,6 +2230,8 @@ class TagType : public Type { protected: TagType(TypeClass TC, const TagDecl *D, QualType can); + virtual Linkage getLinkageImpl() const; + public: TagDecl *getDecl() const { return decl.getPointer(); } @@ -2198,8 +2240,6 @@ public: bool isBeingDefined() const { return decl.getInt(); } void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } - virtual Linkage getLinkage() const; - static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } @@ -2264,68 +2304,6 @@ public: static bool classof(const EnumType *) { return true; } }; -/// ElaboratedType - A non-canonical type used to represents uses of -/// elaborated type specifiers in C++. For example: -/// -/// void foo(union MyUnion); -/// ^^^^^^^^^^^^^ -/// -/// At the moment, for efficiency we do not create elaborated types in -/// C, since outside of typedefs all references to structs would -/// necessarily be elaborated. -class ElaboratedType : public Type, public llvm::FoldingSetNode { -public: - enum TagKind { - TK_struct, - TK_union, - TK_class, - TK_enum - }; - -private: - /// The tag that was used in this elaborated type specifier. - TagKind Tag; - - /// The underlying type. - QualType UnderlyingType; - - explicit ElaboratedType(QualType Ty, TagKind Tag, QualType Canon) - : Type(Elaborated, Canon, Canon->isDependentType()), - Tag(Tag), UnderlyingType(Ty) { } - friend class ASTContext; // ASTContext creates these. - -public: - TagKind getTagKind() const { return Tag; } - QualType getUnderlyingType() const { return UnderlyingType; } - - /// \brief Remove a single level of sugar. - QualType desugar() const { return getUnderlyingType(); } - - /// \brief Returns whether this type directly provides sugar. - bool isSugared() const { return true; } - - static const char *getNameForTagKind(TagKind Kind) { - switch (Kind) { - default: assert(0 && "Unknown TagKind!"); - case TK_struct: return "struct"; - case TK_union: return "union"; - case TK_class: return "class"; - case TK_enum: return "enum"; - } - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getUnderlyingType(), getTagKind()); - } - static void Profile(llvm::FoldingSetNodeID &ID, QualType T, TagKind Tag) { - ID.AddPointer(T.getAsOpaquePtr()); - ID.AddInteger(Tag); - } - - static bool classof(const ElaboratedType*) { return true; } - static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; } -}; - class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { unsigned Depth : 15; unsigned Index : 16; @@ -2592,46 +2570,116 @@ public: static bool classof(const InjectedClassNameType *T) { return true; } }; +/// \brief The kind of a tag type. +enum TagTypeKind { + /// \brief The "struct" keyword. + TTK_Struct, + /// \brief The "union" keyword. + TTK_Union, + /// \brief The "class" keyword. + TTK_Class, + /// \brief The "enum" keyword. + TTK_Enum +}; + /// \brief The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. enum ElaboratedTypeKeyword { - /// \brief No keyword precedes the qualified type name. - ETK_None, - /// \brief The "typename" keyword precedes the qualified type name, e.g., - /// \c typename T::type. - ETK_Typename, - /// \brief The "class" keyword introduces the elaborated-type-specifier. - ETK_Class, /// \brief The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, /// \brief The "union" keyword introduces the elaborated-type-specifier. ETK_Union, + /// \brief The "class" keyword introduces the elaborated-type-specifier. + ETK_Class, /// \brief The "enum" keyword introduces the elaborated-type-specifier. - ETK_Enum + ETK_Enum, + /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// \c typename T::type. + ETK_Typename, + /// \brief No keyword precedes the qualified type name. + ETK_None }; - -/// \brief Represents a type that was referred to via a qualified -/// name, e.g., N::M::type. + +/// A helper class for Type nodes having an ElaboratedTypeKeyword. +/// The keyword in stored in the free bits of the base class. +/// Also provides a few static helpers for converting and printing +/// elaborated type keyword and tag type kind enumerations. +class TypeWithKeyword : public Type { + /// Keyword - Encodes an ElaboratedTypeKeyword enumeration constant. + unsigned Keyword : 3; + +protected: + TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, + QualType Canonical, bool dependent) + : Type(tc, Canonical, dependent), Keyword(Keyword) {} + +public: + virtual ~TypeWithKeyword(); // pin vtable to Type.cpp + + ElaboratedTypeKeyword getKeyword() const { + return static_cast<ElaboratedTypeKeyword>(Keyword); + } + + /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into an elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec); + + /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST) + /// into a tag type kind. It is an error to provide a type specifier + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec); + + /// getKeywordForTagDeclKind - Converts a TagTypeKind into an + /// elaborated type keyword. + static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag); + + /// getTagTypeKindForKeyword - Converts an elaborated type keyword into + // a TagTypeKind. It is an error to provide an elaborated type keyword + /// which *isn't* a tag kind here. + static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword); + + static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword); + + static const char *getKeywordName(ElaboratedTypeKeyword Keyword); + + static const char *getTagTypeKindName(TagTypeKind Kind) { + return getKeywordName(getKeywordForTagTypeKind(Kind)); + } + + class CannotCastToThisType {}; + static CannotCastToThisType classof(const Type *); +}; + +/// \brief Represents a type that was referred to using an elaborated type +/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, +/// or both. /// /// This type is used to keep track of a type name as written in the -/// source code, including any nested-name-specifiers. The type itself -/// is always "sugar", used to express what was written in the source -/// code but containing no additional semantic information. -class QualifiedNameType : public Type, public llvm::FoldingSetNode { +/// source code, including tag keywords and any nested-name-specifiers. +/// The type itself is always "sugar", used to express what was written +/// in the source code but containing no additional semantic information. +class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; /// \brief The type that this qualified name refers to. QualType NamedType; - QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType, - QualType CanonType) - : Type(QualifiedName, CanonType, NamedType->isDependentType()), - NNS(NNS), NamedType(NamedType) { } + ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + QualType NamedType, QualType CanonType) + : TypeWithKeyword(Keyword, Elaborated, CanonType, + NamedType->isDependentType()), + NNS(NNS), NamedType(NamedType) { + assert(!(Keyword == ETK_None && NNS == 0) && + "ElaboratedType cannot have elaborated type keyword " + "and name qualifier both null."); + } friend class ASTContext; // ASTContext creates these public: + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2645,19 +2693,20 @@ public: bool isSugared() const { return true; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, NNS, NamedType); + Profile(ID, getKeyword(), NNS, NamedType); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - QualType NamedType) { + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, QualType NamedType) { + ID.AddInteger(Keyword); ID.AddPointer(NNS); NamedType.Profile(ID); } static bool classof(const Type *T) { - return T->getTypeClass() == QualifiedName; + return T->getTypeClass() == Elaborated; } - static bool classof(const QualifiedNameType *T) { return true; } + static bool classof(const ElaboratedType *T) { return true; } }; /// \brief Represents a qualified type name for which the type name is @@ -2669,10 +2718,8 @@ public: /// typename-specifier), "class", "struct", "union", or "enum" (for a /// dependent elaborated-type-specifier), or nothing (in contexts where we /// know that we must be referring to a type, e.g., in a base class specifier). -class DependentNameType : public Type, public llvm::FoldingSetNode { - /// \brief The keyword used to elaborate this type. - ElaboratedTypeKeyword Keyword; - +class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -2684,16 +2731,16 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : Type(DependentName, CanonType, true), - Keyword(Keyword), NNS(NNS), Name(Name) { + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Name) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, QualType CanonType) - : Type(DependentName, CanonType, true), - Keyword(Keyword), NNS(NNS), Name(Ty) { + : TypeWithKeyword(Keyword, DependentName, CanonType, true), + NNS(NNS), Name(Ty) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } @@ -2701,9 +2748,7 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: - /// \brief Retrieve the keyword used to elaborate this type. - ElaboratedTypeKeyword getKeyword() const { return Keyword; } - + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2727,7 +2772,7 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Keyword, NNS, Name); + Profile(ID, getKeyword(), NNS, Name); } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, @@ -2743,153 +2788,333 @@ public: static bool classof(const DependentNameType *T) { return true; } }; -/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for -/// object oriented design. They basically correspond to C++ classes. There -/// are two kinds of interface types, normal interfaces like "NSString" and -/// qualified interfaces, which are qualified with a protocol list like -/// "NSString<NSCopyable, NSAmazing>". -class ObjCInterfaceType : public Type, public llvm::FoldingSetNode { - ObjCInterfaceDecl *Decl; +/// ObjCObjectType - Represents a class type in Objective C. +/// Every Objective C type is a combination of a base type and a +/// list of protocols. +/// +/// Given the following declarations: +/// @class C; +/// @protocol P; +/// +/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType +/// with base C and no protocols. +/// +/// 'C<P>' is an ObjCObjectType with base C and protocol list [P]. +/// +/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose +/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType +/// and no protocols. +/// +/// 'id<P>' is an ObjCPointerType whose pointee is an ObjCObjecType +/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually +/// this should get its own sugar class to better represent the source. +class ObjCObjectType : public Type { + // Pad the bit count up so that NumProtocols is 2-byte aligned + unsigned : BitsRemainingInType - 16; + + /// \brief The number of protocols stored after the + /// ObjCObjectPointerType node. + /// + /// These protocols are those written directly on the type. If + /// protocol qualifiers ever become additive, the iterators will + /// get kindof complicated. + /// + /// In the canonical object type, these are sorted alphabetically + /// and uniqued. + unsigned NumProtocols : 16; - /// \brief The number of protocols stored after the ObjCInterfaceType node. - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; + /// Either a BuiltinType or an InterfaceType or sugar for either. + QualType BaseType; - ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, - ObjCProtocolDecl **Protos, unsigned NumP); - friend class ASTContext; // ASTContext creates these. + ObjCProtocolDecl * const *getProtocolStorage() const { + return const_cast<ObjCObjectType*>(this)->getProtocolStorage(); + } + + ObjCProtocolDecl **getProtocolStorage(); + +protected: + ObjCObjectType(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, unsigned NumProtocols); + + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(enum Nonce_ObjCInterface) + : Type(ObjCInterface, QualType(), false), + NumProtocols(0), + BaseType(QualType(this_(), 0)) {} + +protected: + Linkage getLinkageImpl() const; // key function + public: - void Destroy(ASTContext& C); + /// getBaseType - Gets the base type of this object type. This is + /// always (possibly sugar for) one of: + /// - the 'id' builtin type (as opposed to the 'id' type visible to the + /// user, which is a typedef for an ObjCPointerType) + /// - the 'Class' builtin type (same caveat) + /// - an ObjCObjectType (currently always an ObjCInterfaceType) + QualType getBaseType() const { return BaseType; } + + bool isObjCId() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); + } + bool isObjCClass() const { + return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); + } + bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } + bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } + bool isObjCUnqualifiedIdOrClass() const { + if (!qual_empty()) return false; + if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>()) + return T->getKind() == BuiltinType::ObjCId || + T->getKind() == BuiltinType::ObjCClass; + return false; + } + bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); } + bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); } - ObjCInterfaceDecl *getDecl() const { return Decl; } + /// Gets the interface declaration for this object type, if the base type + /// really is an interface. + ObjCInterfaceDecl *getInterface() const; + + typedef ObjCProtocolDecl * const *qual_iterator; + + qual_iterator qual_begin() const { return getProtocolStorage(); } + qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); } + + bool qual_empty() const { return getNumProtocols() == 0; } /// getNumProtocols - Return the number of qualifying protocols in this /// interface type, or 0 if there are none. unsigned getNumProtocols() const { return NumProtocols; } - /// \brief Retrieve the Ith protocol. + /// \brief Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; } - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; - qual_iterator qual_begin() const { - return reinterpret_cast<qual_iterator>(this + 1); - } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; - } - bool qual_empty() const { return NumProtocols == 0; } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObject || + T->getTypeClass() == ObjCInterface; + } + static bool classof(const ObjCObjectType *) { return true; } +}; + +/// ObjCObjectTypeImpl - A class providing a concrete implementation +/// of ObjCObjectType, so as to not increase the footprint of +/// ObjCInterfaceType. Code outside of ASTContext and the core type +/// system should not reference this type. +class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { + friend class ASTContext; + + // If anyone adds fields here, ObjCObjectType::getProtocolStorage() + // will need to be modified. + + ObjCObjectTypeImpl(QualType Canonical, QualType Base, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) + : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} + +public: + void Destroy(ASTContext& C); // key function + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, - const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl * const *protocols, - unsigned NumProtocols); + QualType Base, + ObjCProtocolDecl *const *protocols, + unsigned NumProtocols); +}; - virtual Linkage getLinkage() const; +inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { + return reinterpret_cast<ObjCProtocolDecl**>( + static_cast<ObjCObjectTypeImpl*>(this) + 1); +} + +/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for +/// object oriented design. They basically correspond to C++ classes. There +/// are two kinds of interface types, normal interfaces like "NSString" and +/// qualified interfaces, which are qualified with a protocol list like +/// "NSString<NSCopyable, NSAmazing>". +/// +/// ObjCInterfaceType guarantees the following properties when considered +/// as a subtype of its superclass, ObjCObjectType: +/// - There are no protocol qualifiers. To reinforce this, code which +/// tries to invoke the protocol methods via an ObjCInterfaceType will +/// fail to compile. +/// - It is its own base type. That is, if T is an ObjCInterfaceType*, +/// T->getBaseType() == QualType(T, 0). +class ObjCInterfaceType : public ObjCObjectType { + ObjCInterfaceDecl *Decl; + + ObjCInterfaceType(const ObjCInterfaceDecl *D) + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast<ObjCInterfaceDecl*>(D)) {} + friend class ASTContext; // ASTContext creates these. +public: + void Destroy(ASTContext& C); // key function + + /// getDecl - Get the declaration of this interface. + ObjCInterfaceDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == ObjCInterface; } static bool classof(const ObjCInterfaceType *) { return true; } + + // Nonsense to "hide" certain members of ObjCObjectType within this + // class. People asking for protocols on an ObjCInterfaceType are + // not going to get what they want: ObjCInterfaceTypes are + // guaranteed to have no protocols. + enum { + qual_iterator, + qual_begin, + qual_end, + getNumProtocols, + getProtocol + }; }; -/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>', -/// and 'Interface <p> *'. +inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { + if (const ObjCInterfaceType *T = + getBaseType()->getAs<ObjCInterfaceType>()) + return T->getDecl(); + return 0; +} + +/// ObjCObjectPointerType - Used to represent a pointer to an +/// Objective C object. These are constructed from pointer +/// declarators when the pointee type is an ObjCObjectType (or sugar +/// for one). In addition, the 'id' and 'Class' types are typedefs +/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>' +/// are translated into these. /// -/// Duplicate protocols are removed and protocol list is canonicalized to be in -/// alphabetical order. +/// Pointers to pointers to Objective C objects are still PointerTypes; +/// only the first level of pointer gets it own type implementation. class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; // A builtin or interface type. - - /// \brief The number of protocols stored after the ObjCObjectPointerType - /// node. - /// - /// The list of protocols is sorted on protocol name. No protocol is enterred - /// more than once. - unsigned NumProtocols; + QualType PointeeType; - ObjCObjectPointerType(QualType Canonical, QualType T, - ObjCProtocolDecl **Protos, unsigned NumP); + ObjCObjectPointerType(QualType Canonical, QualType Pointee) + : Type(ObjCObjectPointer, Canonical, false), + PointeeType(Pointee) {} friend class ASTContext; // ASTContext creates these. +protected: + virtual Linkage getLinkageImpl() const; + public: void Destroy(ASTContext& C); - // Get the pointee type. Pointee will either be: - // - a built-in type (for 'id' and 'Class'). - // - an interface type (for user-defined types). - // - a TypedefType whose canonical type is an interface (as in 'T' below). - // For example: typedef NSObject T; T *var; + /// getPointeeType - Gets the type pointed to by this ObjC pointer. + /// The result will always be an ObjCObjectType or sugar thereof. QualType getPointeeType() const { return PointeeType; } + /// getObjCObjectType - Gets the type pointed to by this ObjC + /// pointer. This method always returns non-null. + /// + /// This method is equivalent to getPointeeType() except that + /// it discards any typedefs (or other sugar) between this + /// type and the "outermost" object type. So for: + /// @class A; @protocol P; @protocol Q; + /// typedef A<P> AP; + /// typedef A A1; + /// typedef A1<P> A1P; + /// typedef A1P<Q> A1PQ; + /// For 'A*', getObjectType() will return 'A'. + /// For 'A<P>*', getObjectType() will return 'A<P>'. + /// For 'AP*', getObjectType() will return 'A<P>'. + /// For 'A1*', getObjectType() will return 'A'. + /// For 'A1<P>*', getObjectType() will return 'A1<P>'. + /// For 'A1P*', getObjectType() will return 'A1<P>'. + /// For 'A1PQ*', getObjectType() will return 'A1<Q>', because + /// adding protocols to a protocol-qualified base discards the + /// old qualifiers (for now). But if it didn't, getObjectType() + /// would return 'A1P<Q>' (and we'd have to make iterating over + /// qualifiers more complicated). + const ObjCObjectType *getObjectType() const { + return PointeeType->getAs<ObjCObjectType>(); + } + + /// getInterfaceType - If this pointer points to an Objective C + /// @interface type, gets the type for that interface. Any protocol + /// qualifiers on the interface are ignored. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' const ObjCInterfaceType *getInterfaceType() const { - return PointeeType->getAs<ObjCInterfaceType>(); + return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>(); } - /// getInterfaceDecl - returns an interface decl for user-defined types. + + /// getInterfaceDecl - If this pointer points to an Objective @interface + /// type, gets the declaration for that interface. + /// + /// \return null if the base type for this pointer is 'id' or 'Class' ObjCInterfaceDecl *getInterfaceDecl() const { - return getInterfaceType() ? getInterfaceType()->getDecl() : 0; + return getObjectType()->getInterface(); } - /// isObjCIdType - true for "id". + + /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if + /// its object type is the primitive 'id' type with no protocols. bool isObjCIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedId(); } - /// isObjCClassType - true for "Class". + + /// isObjCClassType - True if this is equivalent to the 'Class' type, + /// i.e. if its object tive is the primitive 'Class' type with no protocols. bool isObjCClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - !NumProtocols; + return getObjectType()->isObjCUnqualifiedClass(); } - /// isObjCQualifiedIdType - true for "id <p>". + /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some + /// non-empty set of protocols. bool isObjCQualifiedIdType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && - NumProtocols; + return getObjectType()->isObjCQualifiedId(); } - /// isObjCQualifiedClassType - true for "Class <p>". + + /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for + /// some non-empty set of protocols. bool isObjCQualifiedClassType() const { - return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && - NumProtocols; + return getObjectType()->isObjCQualifiedClass(); } - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef ObjCProtocolDecl* const * qual_iterator; + + /// An iterator over the qualifiers on the object type. Provided + /// for convenience. This will always iterate over the full set of + /// protocols on a type, not just those provided directly. + typedef ObjCObjectType::qual_iterator qual_iterator; qual_iterator qual_begin() const { - return reinterpret_cast<qual_iterator> (this + 1); + return getObjectType()->qual_begin(); } - qual_iterator qual_end() const { - return qual_begin() + NumProtocols; + qual_iterator qual_end() const { + return getObjectType()->qual_end(); } - bool qual_empty() const { return NumProtocols == 0; } + bool qual_empty() const { return getObjectType()->qual_empty(); } - /// getNumProtocols - Return the number of qualifying protocols in this - /// interface type, or 0 if there are none. - unsigned getNumProtocols() const { return NumProtocols; } + /// getNumProtocols - Return the number of qualifying protocols on + /// the object type. + unsigned getNumProtocols() const { + return getObjectType()->getNumProtocols(); + } - /// \brief Retrieve the Ith protocol. + /// \brief Retrieve a qualifying protocol by index on the object + /// type. ObjCProtocolDecl *getProtocol(unsigned I) const { - assert(I < getNumProtocols() && "Out-of-range protocol access"); - return qual_begin()[I]; + return getObjectType()->getProtocol(I); } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual Linkage getLinkage() const; - - void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, QualType T, - ObjCProtocolDecl *const *protocols, - unsigned NumProtocols); + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { + ID.AddPointer(T.getAsOpaquePtr()); + } static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } @@ -3128,12 +3353,6 @@ inline QualType QualType::getNonReferenceType() const { return *this; } -inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { - if (const PointerType *PT = getAs<PointerType>()) - return PT->getPointeeType()->getAs<ObjCInterfaceType>(); - return 0; -} - inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } @@ -3200,8 +3419,8 @@ inline bool Type::isExtVectorType() const { inline bool Type::isObjCObjectPointerType() const { return isa<ObjCObjectPointerType>(CanonicalType); } -inline bool Type::isObjCInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType); +inline bool Type::isObjCObjectType() const { + return isa<ObjCObjectType>(CanonicalType); } inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) @@ -3250,13 +3469,11 @@ inline bool Type::isOverloadableType() const { inline bool Type::hasPointerRepresentation() const { return (isPointerType() || isReferenceType() || isBlockPointerType() || - isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType() || isNullPtrType()); + isObjCObjectPointerType() || isNullPtrType()); } inline bool Type::hasObjCPointerRepresentation() const { - return (isObjCInterfaceType() || isObjCObjectPointerType() || - isObjCQualifiedInterfaceType()); + return isObjCObjectPointerType(); } /// Insertion operator for diagnostics. This allows sending QualType's into a diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index a51da7474d37..f988f0e33b39 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/Decl.h" #include "clang/AST/TemplateBase.h" #include "clang/Basic/Specifiers.h" @@ -84,21 +85,20 @@ public: return Data; } + /// \brief Get the begin source location. + SourceLocation getBeginLoc() const; + + /// \brief Get the end source location. + SourceLocation getEndLoc() const; + /// \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); + SourceRange getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); } /// \brief Get the local source range. - SourceRange getSourceRange() const { - return getSourceRangeImpl(*this); + SourceRange getLocalSourceRange() const { + return getLocalSourceRangeImpl(*this); } /// \brief Returns the size of the type source info data block. @@ -137,9 +137,14 @@ public: private: static void initializeImpl(TypeLoc TL, SourceLocation Loc); static TypeLoc getNextTypeLocImpl(TypeLoc TL); - static SourceRange getSourceRangeImpl(TypeLoc TL); + static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; +/// \brief Return the TypeLoc for a type source info. +inline TypeLoc TypeSourceInfo::getTypeLoc() const { + return TypeLoc(Ty, (void*)(this + 1)); +} + /// \brief Wrapper of type source information for a type with /// no direct quqlaifiers. class UnqualTypeLoc : public TypeLoc { @@ -168,7 +173,7 @@ public: /// type qualifiers. class QualifiedTypeLoc : public TypeLoc { public: - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(); } @@ -263,6 +268,16 @@ public: return TypeClass::classof(Ty); } + static bool classof(const TypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const UnqualTypeLoc *TL) { + return Derived::classofType(TL->getTypePtr()); + } + static bool classof(const Derived *TL) { + return true; + } + TypeLoc getNextTypeLoc() const { return getNextTypeLoc(asDerived()->getInnerType()); } @@ -361,7 +376,7 @@ public: void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } void initializeLocal(SourceLocation Loc) { @@ -413,7 +428,7 @@ public: return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getBuiltinLoc(), getBuiltinLoc()); } @@ -553,6 +568,7 @@ class SubstTemplateTypeParmTypeLoc : struct ObjCProtocolListLocInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; + bool HasBaseTypeAsWritten; }; // A helper class for defining ObjC TypeLocs that can qualified with @@ -560,24 +576,15 @@ struct ObjCProtocolListLocInfo { // // TypeClass basically has to be either ObjCInterfaceType or // ObjCObjectPointerType. -template <class Derived, class TypeClass, class LocalData> -class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, - Derived, - TypeClass, - LocalData> { +class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCObjectTypeLoc, + ObjCObjectType, + ObjCProtocolListLocInfo> { // SourceLocations are stored after Info, one for each Protocol. SourceLocation *getProtocolLocArray() const { return (SourceLocation*) this->getExtraLocalData(); } -protected: - void initializeLocalBase(SourceLocation Loc) { - setLAngleLoc(Loc); - setRAngleLoc(Loc); - for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) - setProtocolLoc(i, Loc); - } - public: SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; @@ -611,29 +618,49 @@ public: return *(this->getTypePtr()->qual_begin() + i); } - SourceRange getSourceRange() const { + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseTypeAsWritten; + } + + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseTypeAsWritten = HasBaseType; + } + + TypeLoc getBaseLoc() const { + return getInnerTypeLoc(); + } + + SourceRange getLocalSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); + setHasBaseTypeAsWritten(true); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) + setProtocolLoc(i, Loc); } unsigned getExtraLocalDataSize() const { return this->getNumProtocols() * sizeof(SourceLocation); } + + QualType getInnerType() const { + return getTypePtr()->getBaseType(); + } }; -struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { +struct ObjCInterfaceLocInfo { SourceLocation NameLoc; }; /// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : - public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc, - ObjCInterfaceType, - ObjCInterfaceLocInfo> { +class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ObjCInterfaceTypeLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { public: ObjCInterfaceDecl *getIFaceDecl() const { return getTypePtr()->getDecl(); @@ -647,85 +674,16 @@ public: getLocalData()->NameLoc = Loc; } - SourceRange getSourceRange() const { - if (getNumProtocols()) - return SourceRange(getNameLoc(), getRAngleLoc()); - else - return SourceRange(getNameLoc(), getNameLoc()); + SourceRange getLocalSourceRange() const { + return SourceRange(getNameLoc()); } void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); setNameLoc(Loc); } }; -struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { - SourceLocation StarLoc; - bool HasProtocols; - bool HasBaseType; -}; - -/// Wraps an ObjCPointerType with source location information. Note -/// that not all ObjCPointerTypes actually have a star location; nor -/// are protocol locations necessarily written in the source just -/// because they're present on the type. -class ObjCObjectPointerTypeLoc : - public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc, - ObjCObjectPointerType, - ObjCObjectPointerLocInfo> { -public: - bool hasProtocolsAsWritten() const { - return getLocalData()->HasProtocols; - } - - void setHasProtocolsAsWritten(bool HasProtocols) { - getLocalData()->HasProtocols = HasProtocols; - } - - bool hasBaseTypeAsWritten() const { - return getLocalData()->HasBaseType; - } - - void setHasBaseTypeAsWritten(bool HasBaseType) { - getLocalData()->HasBaseType = HasBaseType; - } - - SourceLocation getStarLoc() const { - return getLocalData()->StarLoc; - } - - void setStarLoc(SourceLocation Loc) { - getLocalData()->StarLoc = Loc; - } - - SourceRange getSourceRange() const { - // Being written with protocols is incompatible with being written - // with a star. - if (hasProtocolsAsWritten()) - return SourceRange(getLAngleLoc(), getRAngleLoc()); - else - return SourceRange(getStarLoc(), getStarLoc()); - } - - void initializeLocal(SourceLocation Loc) { - initializeLocalBase(Loc); - setHasProtocolsAsWritten(false); - setHasBaseTypeAsWritten(false); - setStarLoc(Loc); - } - - TypeLoc getBaseTypeLoc() const { - return getInnerTypeLoc(); - } - - QualType getInnerType() const { - return getTypePtr()->getPointeeType(); - } -}; - - struct PointerLikeLocInfo { SourceLocation StarLoc; }; @@ -746,7 +704,7 @@ public: return this->getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getSigilLoc(), getSigilLoc()); } @@ -798,6 +756,20 @@ public: } }; +/// Wraps an ObjCPointerType with source location information. +class ObjCObjectPointerTypeLoc : + public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, + ObjCObjectPointerType> { +public: + SourceLocation getStarLoc() const { + return getSigilLoc(); + } + + void setStarLoc(SourceLocation Loc) { + setSigilLoc(Loc); + } +}; + class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, ReferenceType> { @@ -871,13 +843,11 @@ public: ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; } void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } - TypeLoc getArgLoc(unsigned i) const; - TypeLoc getResultLoc() const { return getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } @@ -950,7 +920,7 @@ public: return getInnerTypeLoc(); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getLBracketLoc(), getRBracketLoc()); } @@ -1055,7 +1025,7 @@ public: memcpy(Data, Loc.Data, size); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getTemplateNameLoc(), getRAngleLoc()); } @@ -1183,7 +1153,7 @@ public: setRParenLoc(range.getEnd()); } - SourceRange getSourceRange() const { + SourceRange getLocalSourceRange() const { return SourceRange(getTypeofLoc(), getRParenLoc()); } @@ -1204,7 +1174,7 @@ public: // Reimplemented to account for GNU/C++ extension // typeof unary-expression // where there are no parentheses. - SourceRange getSourceRange() const; + SourceRange getLocalSourceRange() const; }; class TypeOfTypeLoc @@ -1227,24 +1197,110 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DecltypeType> { }; -// FIXME: location of the tag keyword. -class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - ElaboratedTypeLoc, - ElaboratedType> { +struct ElaboratedLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; }; -// FIXME: locations for the nested name specifier; at the very least, -// a SourceRange. -class QualifiedNameTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - QualifiedNameTypeLoc, - QualifiedNameType> { +class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + ElaboratedTypeLoc, + ElaboratedType, + ElaboratedLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + if (getQualifierRange().getEnd().isValid()) + return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + else + return SourceRange(getKeywordLoc()); + else + return getQualifierRange(); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + } + + TypeLoc getNamedTypeLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return getTypePtr()->getNamedType(); + } + + void copy(ElaboratedTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } }; -// FIXME: locations for the typename keyword and nested name specifier. -class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DependentNameTypeLoc, - DependentNameType> { +struct DependentNameLocInfo { + SourceLocation KeywordLoc; + SourceRange QualifierRange; + SourceLocation NameLoc; +}; + +class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + DependentNameTypeLoc, + DependentNameType, + DependentNameLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + return SourceRange(getKeywordLoc(), getNameLoc()); + else + return SourceRange(getQualifierRange().getBegin(), getNameLoc()); + } + + void copy(DependentNameTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + setNameLoc(Loc); + } }; } diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index c3b1c68b1fb6..e729488e4313 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -59,6 +59,20 @@ class TypeLocBuilder { grow(Requested); } + /// Pushes a copy of the given TypeLoc onto this builder. The builder + /// must be empty for this to work. + void pushFullCopy(TypeLoc L) { +#ifndef NDEBUG + assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder"); + LastTy = L.getNextTypeLoc().getType(); +#endif + assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder"); + + unsigned Size = L.getFullDataSize(); + TypeLoc Copy = pushImpl(L.getType(), Size); + memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); + } + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs /// previously retrieved from this builder. TypeSpecTypeLoc pushTypeSpec(QualType T) { diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index c665073025f7..02508af67dd8 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -90,10 +90,10 @@ NON_CANONICAL_TYPE(Elaborated, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) -NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) -TYPE(ObjCInterface, Type) +TYPE(ObjCObject, Type) +TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) #ifdef LAST_TYPE diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 19f7f42a897a..5c9c5285a248 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -1,4 +1,4 @@ -//===--- TypeVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===// +//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,7 +25,7 @@ template<typename ImplClass, typename RetTy=void> class TypeVisitor { public: RetTy Visit(Type *T) { - // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { default: assert(0 && "Unknown type class!"); #define ABSTRACT_TYPE(CLASS, PARENT) diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index cbe00827d00a..a548b0b704d1 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -31,9 +31,13 @@ private: IteratorTy ir; friend class UnresolvedSetImpl; + friend class OverloadExpr; explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {} explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) : ir(const_cast<DeclsTy::iterator>(ir)) {} + + IteratorTy getIterator() const { return ir; } + public: UnresolvedSetIterator() {} @@ -81,9 +85,7 @@ public: bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; } }; -/// UnresolvedSet - A set of unresolved declarations. This is needed -/// in a lot of places, but isn't really worth breaking into its own -/// header right now. +/// UnresolvedSet - A set of unresolved declarations. class UnresolvedSetImpl { typedef UnresolvedSetIterator::DeclsTy DeclsTy; diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index fb8d4d5ff53a..075838d45e5c 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -59,7 +59,7 @@ private: protected: ProgramPoint(const void* P, Kind k, const LocationContext *l, const void *tag = 0) - : Data(P, NULL), K(k), L(l), Tag(tag) {} + : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {} ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l, const void *tag = 0) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 6b2912e2e8c2..62f06edb7785 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -423,6 +423,14 @@ public: /// the diagnostic, this returns null. static const char *getWarningOptionForDiag(unsigned DiagID); + /// getWarningOptionForDiag - Return the category number that a specified + /// DiagID belongs to, or 0 if no category. + static unsigned getCategoryNumberForDiag(unsigned DiagID); + + /// getCategoryNameFromID - Given a category ID, return the name of the + /// category. + static const char *getCategoryNameFromID(unsigned CategoryID); + /// \brief Enumeration describing how the the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. enum SFINAEResponse { diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index f6b5d9c5b308..fabf9ebb4498 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -42,7 +42,10 @@ class InGroup<DiagGroup G> { DiagGroup Group = G; } //class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; } -// This defines the diagnostic groups that have references to them. +// This defines all of the named diagnostic categories. +include "DiagnosticCategories.td" + +// This defines all of the named diagnostic groups. include "DiagnosticGroups.td" diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index cc89c7caec3c..d755d99e6be5 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -14,17 +14,20 @@ let Component = "AST" in { def note_expr_divide_by_zero : Note<"division by zero">; // inline asm related. -def err_asm_invalid_escape : Error< - "invalid %% escape in inline assembly string">; -def err_asm_unknown_symbolic_operand_name : Error< - "unknown symbolic operand name in inline assembly string">; +let CategoryName = "Inline Assembly Issue" in { + def err_asm_invalid_escape : Error< + "invalid %% escape in inline assembly string">; + def err_asm_unknown_symbolic_operand_name : Error< + "unknown symbolic operand name in inline assembly string">; + + def err_asm_unterminated_symbolic_operand_name : Error< + "unterminated symbolic operand name in inline assembly string">; + def err_asm_empty_symbolic_operand_name : Error< + "empty symbolic operand name in inline assembly string">; + def err_asm_invalid_operand_number : Error< + "invalid operand number in inline asm string">; +} -def err_asm_unterminated_symbolic_operand_name : Error< - "unterminated symbolic operand name in inline assembly string">; -def err_asm_empty_symbolic_operand_name : Error< - "empty symbolic operand name in inline assembly string">; -def err_asm_invalid_operand_number : Error< - "invalid operand number in inline asm string">; // Importing ASTs def err_odr_variable_type_inconsistent : Error< diff --git a/include/clang/Basic/DiagnosticCategories.td b/include/clang/Basic/DiagnosticCategories.td new file mode 100644 index 000000000000..a02fbdf93fc3 --- /dev/null +++ b/include/clang/Basic/DiagnosticCategories.td @@ -0,0 +1,10 @@ +//==--- DiagnosticCategories.td - Diagnostic Category Definitions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +class CatInlineAsm : DiagCategory<"Inline Assembly Issue">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 3b7272e5acc5..f4a31cc5766c 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -49,6 +49,8 @@ def err_drv_no_ast_support : Error< "'%0': unable to use AST files with this tool">; def err_drv_clang_unsupported : Error< "the clang compiler does not support '%0'">; +def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error< + "the clang compiler does not support '%0' for C++ on Darwin/i386">; def err_drv_command_failed : Error< "%0 command failed with exit code %1 (use -v to see invocation)">; def err_drv_command_signalled : Error< diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b73103067017..c7cad7395c0b 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -16,7 +16,8 @@ def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; 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_inline_asm : Error<"%0">; // Error generated by the backend. +// Error generated by the backend. +def err_fe_inline_asm : Error<"%0">, CatInlineAsm; def note_fe_inline_asm_here : Note<"generated from here">; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 1012e91baa77..b79bf8e2edbe 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -40,6 +40,9 @@ def ExtraTokens : DiagGroup<"extra-tokens">; def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; +def CXXHexFloats : DiagGroup<"c++-hex-floats">; + +def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; def FourByteMultiChar : DiagGroup<"four-char-constants">; def : DiagGroup<"idiomatic-parentheses">; def : DiagGroup<"import">; @@ -120,6 +123,7 @@ def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def : DiagGroup<"variadic-macros">; def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversions : DiagGroup<"vector-conversions">; // clang specific +def VLA : DiagGroup<"vla">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def : DiagGroup<"write-strings">; def CharSubscript : DiagGroup<"char-subscripts">; @@ -134,16 +138,17 @@ def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]> // legacy reasons. def Conversion : DiagGroup<"conversion", [DiagGroup<"shorten-64-to-32">]>, - DiagCategory<"Value Conversion">; + DiagCategory<"Value Conversion Issue">; def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) - UnusedValue, UnusedVariable]>; + UnusedValue, UnusedVariable]>, + DiagCategory<"Unused Entity Issue">; // Format settings. def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>, - DiagCategory<"Format String">; + DiagCategory<"Format String Issue">; def FormatSecurity : DiagGroup<"format-security", [Format]>; def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>; def FormatY2K : DiagGroup<"format-y2k", [Format]>; @@ -190,4 +195,4 @@ def NonGCC : DiagGroup<"non-gcc", [SignCompare, Conversion, LiteralRange]>; // A warning group for warnings about GCC extensions. -def GNU : DiagGroup<"gnu", [GNUDesignator]>; +def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 3f765bdfb3b7..848e85c8ba41 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -11,7 +11,7 @@ // Lexer Diagnostics //===----------------------------------------------------------------------===// -let Component = "Lex" in { +let Component = "Lex", CategoryName = "Lexical or Preprocessor Issue" in { def null_in_string : Warning<"null character(s) preserved in string literal">; def null_in_char : Warning<"null character(s) preserved in character literal">; @@ -84,9 +84,9 @@ def err_exponent_has_no_digits : Error<"exponent has no digits">; def ext_imaginary_constant : Extension<"imaginary constants are an extension">; def err_hexconstant_requires_exponent : Error< "hexadecimal floating constants require an exponent">; -def ext_hexconstant_cplusplus : ExtWarn< +def ext_hexconstant_cplusplus : Extension< "hexadecimal floating constants are a C99 feature that is incompatible with " - "C++0x">; + "C++0x">, InGroup<CXXHexFloats>; def ext_hexconstant_invalid : Extension< "hexadecimal floating constants are a C99 feature">; def ext_binary_literal : Extension< diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 27958515462a..934bd0db1e01 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -13,9 +13,12 @@ let Component = "Parse" in { -def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">; +def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">, + CatInlineAsm; def warn_file_asm_volatile : Warning< - "meaningless 'volatile' on asm outside function">; + "meaningless 'volatile' on asm outside function">, CatInlineAsm; + +let CategoryName = "Parse Issue" in { def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; def ext_top_level_semi : Extension< @@ -119,6 +122,8 @@ def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< "attributes can not be specified on namespace alias">; +def err_namespace_nonnamespace_scope : Error< + "namespaces can only be defined in global or namespace scope">; def err_expected_semi_after_attribute_list : Error< "expected ';' after attribute list">; def err_expected_semi_after_static_assert : Error< @@ -129,7 +134,7 @@ 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">; def err_expected_asm_operand : Error< - "expected string literal or '[' for asm operand">; + "expected string literal or '[' for asm operand">, CatInlineAsm; def err_expected_selector_for_method : Error< "expected selector for Objective-C method">; def err_expected_property_name : Error<"expected property name">; @@ -311,6 +316,9 @@ def err_explicit_instantiation_with_definition : Error< "'template' keyword">; def err_enum_template : Error<"enumeration cannot be a template">; +def err_missing_dependent_template_keyword : Error< + "use 'template' keyword to treat '%0' as a dependent template name">; + // Constructor template diagnostics. def err_out_of_line_constructor_template_id : Error< "out-of-line constructor for %0 cannot have template arguments">; @@ -355,6 +363,13 @@ def warn_pragma_expected_identifier : Warning< "expected identifier in '#pragma %0' - ignored">; def warn_pragma_extra_tokens_at_eol : Warning< "extra tokens at end of '#pragma %0' - ignored">; +// - #pragma options +def warn_pragma_options_expected_align : Warning< + "expected 'align' following '#pragma options' - ignored">; +def warn_pragma_options_expected_equal : Warning< + "expected '=' following '#pragma options align' - ignored">; +def warn_pragma_options_invalid_option : Warning< + "invalid alignment option in '#pragma options align' - ignored">; // - #pragma pack def warn_pragma_pack_invalid_action : Warning< "unknown action for '#pragma pack' - ignored">; @@ -368,4 +383,5 @@ def warn_pragma_unused_expected_var : Warning< def warn_pragma_unused_expected_punc : Warning< "expected ')' or ',' in '#pragma unused'">; +} // end of Parse Issue category. } // end of Parser diagnostics diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6b40820da814..0ba31aee2ff5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// let Component = "Sema" in { +let CategoryName = "Semantic Issue" in { // Constant expressions def err_expr_not_ice : Error< @@ -36,6 +37,28 @@ def warn_float_underflow : Warning< "magnitude of floating-point constant too small for type %0; minimum is %1">, InGroup<LiteralRange>; +// C99 variable-length arrays +def ext_vla : Extension< + "variable length arrays are a C99 feature, accepted as an extension">, + InGroup<VLA>; +def err_vla_non_pod : Error<"variable length array of non-POD element type %0">; +def err_vla_in_sfinae : Error< + "variable length array cannot be formed during template argument deduction">; +def err_array_star_in_function_definition : Error< + "variable length array must be bound in function definition">; +def err_vla_decl_in_file_scope : Error< + "variable length array declaration not allowed at file scope">; +def err_vla_decl_has_static_storage : Error< + "variable length array declaration can not have 'static' storage duration">; +def err_vla_decl_has_extern_linkage : Error< + "variable length array declaration can not have 'extern' linkage">; + +// C99 variably modified types +def err_variably_modified_template_arg : Error< + "variably modified type %0 cannot be used as a template argument">; +def err_variably_modified_nontype_template_param : Error< + "non-type template parameter of variably modified type %0">; + // C99 Designated Initializers def err_array_designator_negative : Error< "array designator value '%0' is negative">; @@ -71,11 +94,6 @@ def ext_flexible_array_init : Extension< "flexible array initialization is a GNU extension">, InGroup<GNU>; // Declarations. -def ext_vla : Extension< - "variable length arrays are a C99 feature, accepted as an extension">; -def err_vla_cxx : Error< - "variable length arrays are not permitted in C++">; - def ext_anon_param_requires_type_specifier : Extension< "type specifier required for unnamed parameter, defaults to int">; def err_bad_variable_name : Error< @@ -89,8 +107,6 @@ def warn_unused_exception_param : Warning<"unused exception parameter %0">, InGroup<UnusedExceptionParameter>, DefaultIgnore; def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">; -def err_array_star_in_function_definition : Error< - "variable length array must be bound in function definition">; def warn_unused_function : Warning<"unused function %0">, InGroup<UnusedFunction>, DefaultIgnore; @@ -220,6 +236,12 @@ def err_object_cannot_be_passed_returned_by_value : Error< "interface type %1 cannot be %select{returned|passed}0 by value" "; did you forget * in %1">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; +def warn_pragma_options_align_unsupported_option : Warning< + "unsupported alignment option in '#pragma options align'">; +def warn_pragma_options_align_reset_failed : Warning< + "#pragma options align=reset failed: %0">; +def err_pragma_options_align_mac68k_target_unsupported : Error< + "mac68k alignment pragma is not supported on this target">; def warn_pragma_pack_invalid_alignment : Warning< "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">; // Follow the MSVC implementation. @@ -293,6 +315,8 @@ def warn_conflicting_ret_types : Warning< def warn_conflicting_param_types : Warning< "conflicting parameter types in implementation of %0: %1 vs %2">; +def warn_conflicting_variadic :Warning< + "conflicting variadic declaration of method and its implementation">; def warn_implements_nscopying : Warning< "default assign attribute on property %0 which implements " @@ -503,6 +527,10 @@ def err_access_copy_field : def err_access_copy_base : Error<"base class %0 has %select{private|protected}1 copy constructor">, NoSFINAE; +def err_access_dtor_ivar : + Error<"instance variable of type %0 has %select{private|protected}1 " + "destructor">, + NoSFINAE; def note_previous_access_declaration : Note< "previously declared '%1' here">; def err_access_outside_class : Error< @@ -709,6 +737,7 @@ def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_is_uninit : Warning<"field is uninitialized when used here">, InGroup<DiagGroup<"uninitialized">>; +def err_init_incomplete_type : Error<"initialization of incomplete type %0">; def err_temp_copy_no_viable : Error< "no viable constructor %select{copying variable|copying parameter|" @@ -883,6 +912,12 @@ def warn_impcast_float_precision : Warning< def warn_impcast_float_integer : Warning< "implicit cast turns floating-point number into integer: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_sign : Warning< + "implicit cast changes signedness: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_sign_conditional : Warning< + "operand of ? changes signedness: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit cast loses integer precision: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; @@ -951,8 +986,7 @@ def err_attribute_regparm_invalid_number : Error< // Clang-Specific Attributes def err_attribute_iboutlet : Error< - "iboutlet attribute can only be applied to instance variables or " - "properties">; + "%0 attribute can only be applied to instance variables or properties">; def err_attribute_ibaction: Error< "ibaction attribute can only be applied to Objective-C instance methods">; def err_attribute_overloadable_not_function : Error< @@ -1054,15 +1088,29 @@ def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " "couldn't infer template argument %0">; - +def note_ovl_candidate_inconsistent_deduction : Note< + "candidate template ignored: deduced conflicting %select{types|values|" + "templates}0 for parameter %1 (%2 vs. %3)">; +def note_ovl_candidate_explicit_arg_mismatch_named : Note< + "candidate template ignored: invalid explicitly-specified argument " + "for template parameter %0">; +def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< + "candidate template ignored: invalid explicitly-specified argument " + "for %ordinal0 template parameter">; +def note_ovl_candidate_instantiation_depth : Note< + "candidate template ignored: substitution exceeded maximum template " + "instantiation depth">; +def note_ovl_candidate_substitution_failure : Note< + "candidate template ignored: substitution failure %0">; + // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " "%select{function|function|constructor|function|function|constructor|" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" - "function (the implicit copy assignment operator)}0 not viable: requires" - "%select{ at least| at most|}2 %3 argument%s3, but %4 %plural{1:was|:were}4 " - "provided">; + "function (the implicit copy assignment operator)}0 %select{|template }1" + "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 " + "%plural{1:was|:were}4 provided">; def note_ovl_candidate_deleted : Note< "candidate %select{function|function|constructor|" @@ -1484,6 +1532,12 @@ def err_explicit_instantiation_out_of_scope : Error< "explicit instantiation of %0 not in a namespace enclosing %1">; def err_explicit_instantiation_must_be_global : Error< "explicit instantiation of %0 must occur at global scope">; +def warn_explicit_instantiation_out_of_scope_0x : Warning< + "explicit instantiation of %0 not in a namespace enclosing %1">, + InGroup<DiagGroup<"-Wc++0x-compat"> >; +def warn_explicit_instantiation_must_be_global_0x : Warning< + "explicit instantiation of %0 must occur at global scope">, + InGroup<DiagGroup<"-Wc++0x-compat"> >; def err_explicit_instantiation_requires_name : Error< "explicit instantiation declaration requires a name">; @@ -1512,6 +1566,9 @@ def err_explicit_instantiation_without_qualified_id_quals : Error< "qualifier in explicit instantiation of '%0%1' requires a template-id">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< "explicit instantiation of %q0 must occur in %1">; +def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning< + "explicit instantiation of %q0 must occur in %1">, + InGroup<DiagGroup<"c++0x-compat"> >; def err_explicit_instantiation_undefined_member : Error< "explicit instantiation of undefined %select{member class|member function|" "static data member}0 %1 of class template %2">; @@ -1631,12 +1688,6 @@ def warn_enumerator_too_large : Warning< def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; -def err_vla_decl_in_file_scope : Error< - "variable length array declaration not allowed at file scope">; -def err_vla_decl_has_static_storage : Error< - "variable length array declaration can not have 'static' storage duration">; -def err_vla_decl_has_extern_linkage : Error< - "variable length array declaration can not have 'extern' linkage">; def err_vm_decl_in_file_scope : Error< "variably modified type declaration not allowed at file scope">; def err_vm_decl_has_extern_linkage : Error< @@ -1725,20 +1776,20 @@ def err_undeclared_label_use : Error<"use of undeclared label '%0'">; def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; def err_switch_into_protected_scope : Error< "illegal switch case into protected scope">; -def err_indirect_goto_in_protected_scope : Warning< - "illegal indirect goto in protected scope, unknown effect on scopes">, - InGroup<DiagGroup<"label-address-scope">>; -def err_addr_of_label_in_protected_scope : Warning< - "address taken of label in protected scope, jump to it would have " - "unknown effect on scope">, InGroup<DiagGroup<"label-address-scope">>; +def err_indirect_goto_without_addrlabel : Error< + "indirect goto in function with no address-of-label expressions">; +def warn_indirect_goto_in_protected_scope : Warning< + "indirect goto might cross protected scopes">, + InGroup<DiagGroup<"label-address-scope">>; +def note_indirect_goto_target : Note<"possible target of indirect goto">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; +def note_protected_by_cleanup : Note< + "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; -def note_protected_by_cleanup : Note< - "jump bypasses initialization of declaration with __attribute__((cleanup))">; def note_protected_by_objc_try : Note< "jump bypasses initialization of @try block">; def note_protected_by_objc_catch : Note< @@ -1754,6 +1805,25 @@ def note_protected_by_cxx_catch : Note< def note_protected_by___block : Note< "jump bypasses setup of __block variable">; +def note_exits_cleanup : Note< + "jump exits scope of variable with __attribute__((cleanup))">; +def note_exits_dtor : Note< + "jump exits scope of variable with non-trivial destructor">; +def note_exits___block : Note< + "jump exits scope of __block variable">; +def note_exits_objc_try : Note< + "jump exits @try block">; +def note_exits_objc_catch : Note< + "jump exits @catch block">; +def note_exits_objc_finally : Note< + "jump exits @finally block">; +def note_exits_objc_synchronized : Note< + "jump exits @synchronized block">; +def note_exits_cxx_try : Note< + "jump exits try block">; +def note_exits_cxx_catch : Note< + "jump exits catch block">; + def err_func_returning_array_function : Error< "function cannot return %select{array|function}0 type %1">; def err_field_declared_as_function : Error<"field %0 declared as a function">; @@ -1764,6 +1834,8 @@ def ext_variable_sized_type_in_struct : ExtWarn< def err_flexible_array_empty_struct : Error< "flexible array %0 not allowed in otherwise empty struct">; +def err_flexible_array_has_nonpod_type : Error< + "flexible array member %0 of non-POD element type %1">; def ext_flexible_array_in_struct : Extension< "%0 may not be nested in a struct due to flexible array member">; def ext_flexible_array_in_array : Extension< @@ -1806,6 +1878,9 @@ def err_func_def_incomplete_result : Error< // Expressions. def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>; +def err_sizeof_alignof_overloaded_function_type : Error< + "invalid application of '%select{sizeof|__alignof}0' to an overloaded " + "function">; def ext_sizeof_void_type : Extension< "invalid application of '%0' to a void type">, InGroup<PointerArith>; def err_sizeof_alignof_incomplete_type : Error< @@ -2196,6 +2271,8 @@ def err_default_init_const : Error< "default initialization of an object of const type %0" "%select{| requires a user-provided default constructor}1">; def err_delete_operand : Error<"cannot delete expression of type %0">; +def ext_delete_void_ptr_operand : ExtWarn< + "cannot delete expression with pointer-to-'void' type %0">; def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< @@ -2293,7 +2370,9 @@ def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; def err_incomplete_object_call : Error< "incomplete type in call to object of type %0">; - +def err_incomplete_pointer_to_member_return : Error< + "incomplete return type %0 of pointer-to-member constant">; + def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, InGroup<Parentheses>; @@ -2510,31 +2589,35 @@ def warn_unused_call : Warning< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">; - -// inline asm. -def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; -def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; -def err_asm_invalid_output_constraint : Error< - "invalid output constraint '%0' in asm">; -def err_asm_invalid_lvalue_in_input : Error< - "invalid lvalue in asm input for constraint '%0'">; -def err_asm_invalid_input_constraint : Error< - "invalid input constraint '%0' in asm">; -def err_asm_invalid_type_in_input : Error< - "invalid type %0 in asm input for constraint '%1'">; -def err_asm_tying_incompatible_types : Error< - "unsupported inline asm: input with type %0 matching output with type %1">; -def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; -def err_invalid_asm_cast_lvalue : Error< - "invalid use of a cast in a inline asm context requiring an l-value: " - "remove the cast or build with -fheinous-gnu-extensions">; - -def warn_invalid_asm_cast_lvalue : Warning< - "invalid use of a cast in a inline asm context requiring an l-value: " - "accepted due to -fheinous-gnu-extensions, but clang may remove support " - "for this in the future">; +} // End of general sema category. +// inline asm. +let CategoryName = "Inline Assembly Issue" in { + def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; + def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; + def err_asm_invalid_output_constraint : Error< + "invalid output constraint '%0' in asm">; + def err_asm_invalid_lvalue_in_input : Error< + "invalid lvalue in asm input for constraint '%0'">; + def err_asm_invalid_input_constraint : Error< + "invalid input constraint '%0' in asm">; + def err_asm_invalid_type_in_input : Error< + "invalid type %0 in asm input for constraint '%1'">; + def err_asm_tying_incompatible_types : Error< + "unsupported inline asm: input with type %0 matching output with type %1">; + def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; + def err_invalid_asm_cast_lvalue : Error< + "invalid use of a cast in a inline asm context requiring an l-value: " + "remove the cast or build with -fheinous-gnu-extensions">; + + def warn_invalid_asm_cast_lvalue : Warning< + "invalid use of a cast in a inline asm context requiring an l-value: " + "accepted due to -fheinous-gnu-extensions, but clang may remove support " + "for this in the future">; +} + +let CategoryName = "Semantic Issue" in { def err_invalid_conversion_between_vectors : Error< "invalid conversion between vector type %0 and %1 of different size">; @@ -2842,9 +2925,11 @@ def warn_case_value_overflow : Warning< InGroup<DiagGroup<"switch">>; def err_duplicate_case : Error<"duplicate case value '%0'">; def warn_case_empty_range : Warning<"empty case range specified">; +def warn_missing_case_for_condition : + Warning<"no case matching constant switch condition '%0'">; def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">, InGroup<DiagGroup<"switch-enum"> >; -def not_in_enum : Warning<"case value not in enumerated type %0">, +def warn_not_in_enum : Warning<"case value not in enumerated type %0">, InGroup<DiagGroup<"switch-enum"> >; def err_typecheck_statement_requires_scalar : Error< "statement requires expression of scalar type (%0 invalid)">; @@ -3010,6 +3095,6 @@ def err_undeclared_protocol_suggest : Error< def note_base_class_specified_here : Note< "base class %0 specified here">; -} - +} // end of sema category +} // end of sema component. diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 930fb52873eb..6a4be4609433 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -280,6 +280,57 @@ public: /// \brief Read the source location entry with index ID. virtual void ReadSLocEntry(unsigned ID) = 0; }; + + +/// IsBeforeInTranslationUnitCache - This class holds the cache used by +/// isBeforeInTranslationUnit. The cache structure is complex enough to be +/// worth breaking out of SourceManager. +class IsBeforeInTranslationUnitCache { + /// L/R QueryFID - These are the FID's of the cached query. If these match up + /// with a subsequent query, the result can be reused. + FileID LQueryFID, RQueryFID; + + /// CommonFID - This is the file found in common between the two #include + /// traces. It is the nearest common ancestor of the #include tree. + FileID CommonFID; + + /// L/R CommonOffset - This is the offset of the previous query in CommonFID. + /// Usually, this represents the location of the #include for QueryFID, but if + /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a + /// random token in the parent. + unsigned LCommonOffset, RCommonOffset; +public: + + /// isCacheValid - Return true if the currently cached values match up with + /// the specified LHS/RHS query. If not, we can't use the cache. + bool isCacheValid(FileID LHS, FileID RHS) const { + return LQueryFID == LHS && RQueryFID == RHS; + } + + /// getCachedResult - If the cache is valid, compute the result given the + /// specified offsets in the LHS/RHS FID's. + bool getCachedResult(unsigned LOffset, unsigned ROffset) const { + // If one of the query files is the common file, use the offset. Otherwise, + // use the #include loc in the common file. + if (LQueryFID != CommonFID) LOffset = LCommonOffset; + if (RQueryFID != CommonFID) ROffset = RCommonOffset; + return LOffset < ROffset; + } + + // Set up a new query. + void setQueryFIDs(FileID LHS, FileID RHS) { + LQueryFID = LHS; + RQueryFID = RHS; + } + + void setCommonLoc(FileID commonFID, unsigned lCommonOffset, + unsigned rCommonOffset) { + CommonFID = commonFID; + LCommonOffset = lCommonOffset; + RCommonOffset = rCommonOffset; + } + +}; /// SourceManager - This file handles loading and caching of source files into /// memory. This object owns the MemoryBuffer objects for all of the loaded @@ -347,9 +398,7 @@ class SourceManager { mutable unsigned NumLinearScans, NumBinaryProbes; // Cache results for the isBeforeInTranslationUnit method. - mutable FileID LastLFIDForBeforeTUCheck; - mutable FileID LastRFIDForBeforeTUCheck; - mutable bool LastResForBeforeTUCheck; + mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&); diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 19987508baf3..00fd9b92e13e 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -58,6 +58,8 @@ protected: const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; + unsigned HasAlignMac68kSupport : 1; + // TargetInfo Constructor. Default initializes all fields. TargetInfo(const std::string &T); @@ -210,6 +212,12 @@ public: return UseBitFieldTypeAlignment; } + /// hasAlignMac68kSupport - Check whether this target support '#pragma options + /// align=mac68k'. + bool hasAlignMac68kSupport() const { + return HasAlignMac68kSupport; + } + /// getTypeName - Return the user string for the specified integer type enum. /// For example, SignedShort -> "short". static const char *getTypeName(IntType T); diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 52e83f4045ef..b16b82854b1c 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -220,7 +220,7 @@ KEYWORD(unsigned , KEYALL) KEYWORD(void , KEYALL) KEYWORD(volatile , KEYALL) KEYWORD(while , KEYALL) -KEYWORD(_Bool , KEYALL) +KEYWORD(_Bool , KEYNOMS) KEYWORD(_Complex , KEYALL) KEYWORD(_Imaginary , KEYALL) KEYWORD(__func__ , KEYALL) @@ -336,6 +336,7 @@ KEYWORD(__declspec , KEYALL) KEYWORD(__cdecl , KEYALL) KEYWORD(__stdcall , KEYALL) KEYWORD(__fastcall , KEYALL) +KEYWORD(__thiscall , KEYALL) KEYWORD(__forceinline , KEYALL) // Altivec Extension. @@ -372,6 +373,7 @@ ALIAS("_asm" , asm , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS) ALIAS("_fastcall" , __fastcall , KEYMS) ALIAS("_stdcall" , __stdcall , KEYMS) +ALIAS("_thiscall" , __thiscall , KEYMS) //===----------------------------------------------------------------------===// // Objective-C @-preceeded keywords. diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt index 61d2bf602d9a..c2880481a2e9 100644 --- a/include/clang/CMakeLists.txt +++ b/include/clang/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(AST) add_subdirectory(Basic) add_subdirectory(Driver) diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h index 0c59d7b572a4..3c7cb68c0943 100644 --- a/include/clang/Checker/PathSensitive/AnalysisManager.h +++ b/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -37,8 +37,12 @@ class AnalysisManager : public BugReporterData { enum AnalysisScope { ScopeTU, ScopeDecl } AScope; + // The maximum number of exploded nodes the analyzer will generate. unsigned MaxNodes; + // The maximum number of times the analyzer will go through a loop. + unsigned MaxLoop; + bool VisualizeEGDot; bool VisualizeEGUbi; bool PurgeDead; @@ -52,19 +56,22 @@ class AnalysisManager : public BugReporterData { // bifurcates paths. bool EagerlyAssume; bool TrimGraph; + bool InlineCall; public: AnalysisManager(ASTContext &ctx, Diagnostic &diags, const LangOptions &lang, PathDiagnosticClient *pd, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, unsigned maxnodes, - bool vizdot, bool vizubi, bool purge, bool eager, bool trim) + unsigned maxloop, + bool vizdot, bool vizubi, bool purge, bool eager, bool trim, + bool inlinecall) : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), - AScope(ScopeDecl), MaxNodes(maxnodes), + AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), - EagerlyAssume(eager), TrimGraph(trim) {} + EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {} ~AnalysisManager() { FlushDiagnostics(); } @@ -108,6 +115,8 @@ public: unsigned getMaxNodes() const { return MaxNodes; } + unsigned getMaxLoop() const { return MaxLoop; } + bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } @@ -122,6 +131,8 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } + bool shouldInlineCall() const { return InlineCall; } + CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); } diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index f04ca75084b7..ac407f6933c8 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -456,6 +456,8 @@ private: void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, const GRState* St, SVal location, const void *tag, bool isLoad); + + bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); }; } // end clang namespace diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 41d7c2bd713e..f3155b9aacd4 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -18,6 +18,7 @@ #include "clang/Checker/PathSensitive/SVals.h" #include "clang/Checker/PathSensitive/ValueManager.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" namespace clang { @@ -143,9 +144,9 @@ public: return UnknownVal(); } - virtual Store RemoveDeadBindings(Store store, Stmt* Loc, - const StackFrameContext *LCtx, - SymbolReaper& SymReaper, + virtual const GRState *RemoveDeadBindings(GRState &state, Stmt* Loc, + const StackFrameContext *LCtx, + SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; @@ -167,10 +168,15 @@ public: // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, - const MemRegion *region, SVal extent) { + const MemRegion *region, SVal extent) { return state; } + virtual llvm::Optional<SVal> getExtent(const GRState *state, + const MemRegion *R) { + return llvm::Optional<SVal>(); + } + /// EnterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. virtual const GRState *EnterStackFrame(const GRState *state, diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 54d3ba03f3f0..6241230ffb45 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -54,6 +54,7 @@ public: unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned RelaxAll : 1; /// Relax all machine code instructions. unsigned SoftFloat : 1; /// -soft-float. unsigned TimePasses : 1; /// Set when -ftime-report is enabled. unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization @@ -108,6 +109,7 @@ public: ObjCDispatchMethod = Legacy; OptimizationLevel = 0; OptimizeSize = 0; + RelaxAll = 0; SoftFloat = 0; TimePasses = 0; UnitAtATime = 1; diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 0a8eaeaf238f..7a14ae84d466 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -17,12 +17,15 @@ #include <list> #include <string> +#include <vector> namespace llvm { class Twine; } namespace clang { + class Diagnostic; + namespace driver { class Arg; class ArgList; @@ -175,6 +178,25 @@ namespace driver { /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; + + /// @} + /// @name Argument Lookup Utilities + /// @{ + + /// getLastArgValue - Return the value of the last argument, or a default. + llvm::StringRef getLastArgValue(OptSpecifier Id, + llvm::StringRef Default = "") const; + + /// getLastArgValue - Return the value of the last argument as an integer, + /// or a default. Emits an error if the argument is given, but non-integral. + int getLastArgIntValue(OptSpecifier Id, int Default, + Diagnostic &Diags) const; + + /// getAllArgValues - Get the values of all instances of the given argument + /// as strings. + std::vector<std::string> getAllArgValues(OptSpecifier Id) const; + + /// @} /// @name Translation Utilities /// @{ diff --git a/include/clang/Driver/CC1AsOptions.h b/include/clang/Driver/CC1AsOptions.h new file mode 100644 index 000000000000..05082132cee4 --- /dev/null +++ b/include/clang/Driver/CC1AsOptions.h @@ -0,0 +1,32 @@ +//===--- CC1AsOptions.h - Clang Assembler Options Table ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_DRIVER_CC1ASOPTIONS_H +#define CLANG_DRIVER_CC1ASOPTIONS_H + +namespace clang { +namespace driver { + class OptTable; + +namespace cc1asoptions { + enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) OPT_##ID, +#include "clang/Driver/CC1AsOptions.inc" + LastOption +#undef OPTION + }; +} + + OptTable *createCC1AsOptTable(); +} +} + +#endif diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td new file mode 100644 index 000000000000..5c08dc630551 --- /dev/null +++ b/include/clang/Driver/CC1AsOptions.td @@ -0,0 +1,71 @@ +//===--- CC1AsOptions.td - Options for clang -cc1as -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the options accepted by clang -cc1as. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +//===----------------------------------------------------------------------===// +// Target Options +//===----------------------------------------------------------------------===// + +def triple : Separate<"-triple">, + HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; + +//===----------------------------------------------------------------------===// +// Language Options +//===----------------------------------------------------------------------===// + +def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, + HelpText<"Add directory to include search path">; +def n : Flag<"-n">, + HelpText<"Don't automatically start assembly file with a text section">; + +//===----------------------------------------------------------------------===// +// Frontend Options +//===----------------------------------------------------------------------===// + +def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; + +def filetype : Separate<"-filetype">, + HelpText<"Specify the output file type ('asm', 'null', or 'obj')">; + +def help : Flag<"-help">, + HelpText<"Print this help text">; +def _help : Flag<"--help">, Alias<help>; + +def version : Flag<"-version">, + HelpText<"Print the assembler version">; +def _version : Flag<"--version">, Alias<version>; + +// Generic forwarding to LLVM options. This should only be used for debugging +// and experimental features. +def mllvm : Separate<"-mllvm">, + HelpText<"Additional arguments to forward to LLVM's option processing">; + +//===----------------------------------------------------------------------===// +// Transliterate Options +//===----------------------------------------------------------------------===// + +def output_asm_variant : Separate<"-output-asm-variant">, + HelpText<"Select the asm variant index to use for output">; +def show_encoding : Flag<"-show-encoding">, + HelpText<"Show instruction encoding information in transliterate mode">; +def show_inst : Flag<"-show-inst">, + HelpText<"Show internal instruction representation in transliterate mode">; + +//===----------------------------------------------------------------------===// +// Assemble Options +//===----------------------------------------------------------------------===// + +def relax_all : Flag<"-relax-all">, + HelpText<"Relax all fixups (for performance testing)">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 0badeb9efa54..fd8322b84370 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -56,8 +56,6 @@ def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, HelpText<"Run the [Core] Foundation reference count checker">; def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, HelpText<"Warn about unintended use of sizeof() on pointer expressions">; -def analysis_InlineCall : Flag<"-inline-call">, - HelpText<"Experimental transfer function inlining callees when its definition is available.">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -97,8 +95,12 @@ def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, HelpText<"Display exploded graph using GraphViz">; def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, HelpText<"Display exploded graph using Ubigraph">; +def analyzer_inline_call : Flag<"-analyzer-inline-call">, + HelpText<"Experimental transfer function inlining callees when its definition is available.">; def analyzer_max_nodes : Separate<"-analyzer-max-nodes">, HelpText<"The maximum number of nodes the analyzer can generate">; +def analyzer_max_loop : Separate<"-analyzer-max-loop">, + HelpText<"The maximum number of times the analyzer will go through a loop">; //===----------------------------------------------------------------------===// // CodeGen Options @@ -145,6 +147,8 @@ def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; def msoft_float : Flag<"-msoft-float">, HelpText<"Use software floating point">; +def mrelax_all : Flag<"-mrelax-all">, + HelpText<"Relax all machine instructions">; def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, @@ -196,6 +200,9 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang HelpText<"Print source range spans in numeric form">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, HelpText<"Print diagnostic name with mappable diagnostics">; +def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, + HelpText<"Print diagnostic category">; + def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, HelpText<"Set the tab stop distance.">; def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, @@ -238,6 +245,8 @@ def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer"> HelpText<"Don't use the \"debug\" code-completion print">; def code_completion_macros : Flag<"-code-completion-macros">, HelpText<"Include macros in code-completion results">; +def code_completion_patterns : Flag<"-code-completion-patterns">, + HelpText<"Include code patterns in code-completion results">; def disable_free : Flag<"-disable-free">, HelpText<"Disable freeing of memory on exit">; def help : Flag<"-help">, @@ -293,6 +302,8 @@ def ast_dump : Flag<"-ast-dump">, HelpText<"Build ASTs and then debug dump them">; def ast_view : Flag<"-ast-view">, HelpText<"Build ASTs and view them with GraphViz">; +def boostcon : Flag<"-boostcon">, + HelpText<"BoostCon workshop mode">; def print_decl_contexts : Flag<"-print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; def emit_pth : Flag<"-emit-pth">, @@ -307,6 +318,8 @@ def emit_llvm_bc : Flag<"-emit-llvm-bc">, HelpText<"Build ASTs then convert to LLVM, emit .bc file">; def emit_llvm_only : Flag<"-emit-llvm-only">, HelpText<"Build ASTs and convert to LLVM, discarding output">; +def emit_codegen_only : Flag<"-emit-codegen-only">, + HelpText<"Generate machine code, but discard output">; def emit_obj : Flag<"-emit-obj">, HelpText<"Emit native object files">; def rewrite_test : Flag<"-rewrite-test">, diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt index ed9825b59df5..99be53ffc72b 100644 --- a/include/clang/Driver/CMakeLists.txt +++ b/include/clang/Driver/CMakeLists.txt @@ -9,3 +9,9 @@ tablegen(CC1Options.inc -gen-opt-parser-defs) add_custom_target(ClangCC1Options DEPENDS CC1Options.inc) + +set(LLVM_TARGET_DEFINITIONS CC1AsOptions.td) +tablegen(CC1AsOptions.inc + -gen-opt-parser-defs) +add_custom_target(ClangCC1AsOptions + DEPENDS CC1AsOptions.inc) diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile index 18f3e58d7db4..b462aaa24bc9 100644 --- a/include/clang/Driver/Makefile +++ b/include/clang/Driver/Makefile @@ -1,5 +1,5 @@ LEVEL = ../../../../.. -BUILT_SOURCES = Options.inc CC1Options.inc +BUILT_SOURCES = Options.inc CC1Options.inc CC1AsOptions.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -13,4 +13,6 @@ $(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(TBLGEN) $(ObjDir)/.d $(Echo) "Building Clang CC1 Option tables with tblgen" $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< - +$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td OptParser.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang CC1 Assembler Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index f6e69e045444..a9a52c01f45b 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -139,6 +139,7 @@ def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>; def MT : JoinedOrSeparate<"-MT">, Group<M_Group>; def Mach : Flag<"-Mach">; def M : Flag<"-M">, Group<M_Group>; +def O0 : Joined<"-O0">, Group<O_Group>; def O4 : Joined<"-O4">, Group<O_Group>; def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C++ inputs">; @@ -231,6 +232,7 @@ def fPIC : Flag<"-fPIC">, Group<f_Group>; def fPIE : Flag<"-fPIE">, Group<f_Group>; def faccess_control : Flag<"-faccess-control">, Group<f_Group>; def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; +def fasm : Flag<"-fasm">, Group<f_Group>; def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>; def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>; def fastcp : Flag<"-fastcp">, Group<f_Group>; @@ -257,6 +259,7 @@ def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[H def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; +def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>; def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; @@ -265,10 +268,7 @@ def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; - def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>; -def fasm : Flag<"-fasm">, Alias<fgnu_keywords>; - def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; @@ -291,6 +291,7 @@ def fmudflap : Flag<"-fmudflap">, Group<f_Group>; def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>; def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>; +def fno_asm : Flag<"-fno-asm">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>; def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; @@ -306,10 +307,7 @@ def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; - def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; -def fno_asm : Flag<"-fno-asm">, Alias<fno_gnu_keywords>; - def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>; @@ -329,6 +327,7 @@ def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; +def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>; @@ -384,6 +383,8 @@ def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>; +def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>; +def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>; def f : Joined<"-f">, Group<f_Group>; def g0 : Joined<"-g0">, Group<g_Group>; def g3 : Joined<"-g3">, Group<g_Group>; @@ -436,6 +437,7 @@ def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>; def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>; def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>; def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; +def mno_relax_all : Flag<"-mno-relax-all">, Group<m_Group>; def mno_soft_float : Flag<"-mno-soft-float">, Group<m_Group>; def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>; def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>; @@ -453,6 +455,7 @@ def marm : Flag<"-marm">, Alias<mno_thumb>; def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; def mred_zone : Flag<"-mred-zone">, Group<m_Group>; +def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>; def msoft_float : Flag<"-msoft-float">, Group<m_Group>; def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; @@ -667,6 +670,7 @@ def _pipe : Flag<"--pipe">, Alias<pipe>, Flags<[DriverOption]>; def _prefix_EQ : Joined<"--prefix=">, Alias<B>, Flags<[RenderSeparate]>; def _prefix : Separate<"--prefix">, Alias<B>; def _preprocess : Flag<"--preprocess">, Alias<E>; +def _print_diagnostic_categories : Flag<"--print-diagnostic-categories">; def _print_file_name_EQ : Joined<"--print-file-name=">, Alias<print_file_name_EQ>; def _print_file_name : Separate<"--print-file-name">, Alias<print_file_name_EQ>; def _print_libgcc_file_name : Flag<"--print-libgcc-file-name">, Alias<print_libgcc_file_name>; diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index ef77206c6593..4368a81e3a41 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -30,17 +30,23 @@ class Tool { /// The tool name (for debugging). const char *Name; + /// The human readable name for the tool, for use in diagnostics. + const char *ShortName; + /// The tool chain this tool is a part of. const ToolChain &TheToolChain; public: - Tool(const char *Name, const ToolChain &TC); + Tool(const char *Name, const char *ShortName, + const ToolChain &TC); public: virtual ~Tool(); const char *getName() const { return Name; } + const char *getShortName() const { return ShortName; } + const ToolChain &getToolChain() const { return TheToolChain; } virtual bool acceptsPipedInput() const = 0; diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h index 3341bb01f0fa..2cbdf368a893 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalysisConsumer.h @@ -61,6 +61,7 @@ public: AnalysisDiagClients AnalysisDiagOpt; std::string AnalyzeSpecificFunction; unsigned MaxNodes; + unsigned MaxLoop; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; @@ -71,6 +72,8 @@ public: unsigned VisualizeEGUbi : 1; unsigned EnableExperimentalChecks : 1; unsigned EnableExperimentalInternalChecks : 1; + unsigned InlineCall : 1; + public: AnalyzerOptions() { AnalysisStoreOpt = BasicStoreModel; diff --git a/include/clang/Frontend/CodeGenAction.h b/include/clang/Frontend/CodeGenAction.h index a1e3c42075b6..dfc117a0b06c 100644 --- a/include/clang/Frontend/CodeGenAction.h +++ b/include/clang/Frontend/CodeGenAction.h @@ -57,6 +57,11 @@ public: EmitLLVMOnlyAction(); }; +class EmitCodeGenOnlyAction : public CodeGenAction { +public: + EmitCodeGenOnlyAction(); +}; + class EmitObjAction : public CodeGenAction { public: EmitObjAction(); diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 36720c9d1462..06dc8004a652 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -519,7 +519,7 @@ public: createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, bool UseDebugPrinter, bool ShowMacros, - llvm::raw_ostream &OS); + bool ShowCodePatterns, llvm::raw_ostream &OS); /// Create the frontend timer and replace any existing one with it. void createFrontendTimer(); diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index e839a8c4c772..16551ee03e1f 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -84,6 +84,7 @@ NODE_XML(Decl, "FIXME_Decl") ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclKindName(), "unhandled_decl_name") END_NODE_XML NODE_XML(FunctionDecl, "Function") @@ -106,7 +107,7 @@ NODE_XML(FunctionDecl, "Function") SUB_NODE_FN_BODY_XML END_NODE_XML -NODE_XML(CXXMethodDecl, "CXXMethodDecl") +NODE_XML(CXXMethodDecl, "CXXMethod") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getDeclContext(), "context") @@ -116,6 +117,79 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl") ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") ATTRIBUTE_OPT_XML(isStatic(), "static") ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXConstructorDecl, "CXXConstructor") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") + ATTRIBUTE_OPT_XML(isDefaultConstructor(), "is_default_ctor") + ATTRIBUTE_OPT_XML(isCopyConstructor(), "is_copy_ctor") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXDestructorDecl, "CXXDestructor") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML + ATTRIBUTE_XML(getNumParams(), "num_args") + SUB_NODE_SEQUENCE_XML(ParmVarDecl) + SUB_NODE_FN_BODY_XML +END_NODE_XML + +NODE_XML(CXXConversionDecl, "CXXConversion") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") + TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) + ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") + ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") + ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML ATTRIBUTE_XML(getNumParams(), "num_args") SUB_NODE_SEQUENCE_XML(ParmVarDecl) SUB_NODE_FN_BODY_XML @@ -126,6 +200,7 @@ NODE_XML(NamespaceDecl, "Namespace") ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getDeclContext(), "context") ATTRIBUTE_XML(getNameAsString(), "name") + SUB_NODE_SEQUENCE_XML(DeclContext) END_NODE_XML NODE_XML(UsingDirectiveDecl, "UsingDirective") @@ -189,6 +264,12 @@ NODE_XML(FieldDecl, "Field") ATTRIBUTE_XML(getNameAsString(), "name") TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_OPT_XML(isMutable(), "mutable") + ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") + ENUM_XML(AS_none, "") + ENUM_XML(AS_public, "public") + ENUM_XML(AS_protected, "protected") + ENUM_XML(AS_private, "private") + END_ENUM_XML ATTRIBUTE_OPT_XML(isBitField(), "bitfield") SUB_NODE_OPT_XML(Expr) // init expr of a bit field END_NODE_XML @@ -237,6 +318,35 @@ NODE_XML(LinkageSpecDecl, "LinkageSpec") END_ENUM_XML END_NODE_XML +NODE_XML(TemplateDecl, "Template") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(TemplateTypeParmDecl, "TemplateTypeParm") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getNameAsString(), "name") +END_NODE_XML + +NODE_XML(UsingShadowDecl, "UsingShadow") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getTargetDecl(), "target_decl") + ATTRIBUTE_XML(getUsingDecl(), "using_decl") +END_NODE_XML + +NODE_XML(UsingDecl, "Using") + ID_ATTRIBUTE_XML + ATTRIBUTE_FILE_LOCATION_XML + ATTRIBUTE_XML(getDeclContext(), "context") + ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl") + ATTRIBUTE_XML(isTypeName(), "is_typename") +END_NODE_XML //===----------------------------------------------------------------------===// #undef NODE_XML diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index b4f147bde7b7..8eb66e57da92 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -30,6 +30,8 @@ public: unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable /// diagnostics. + unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, + /// 2 -> Full Name. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected /// diagnostics, indicated by markers in the @@ -74,12 +76,13 @@ public: ShowFixits = 1; ShowLocation = 1; ShowOptionNames = 0; + ShowCategories = 0; ShowSourceRanges = 0; VerifyDiagnostics = 0; BinaryOutput = 0; ErrorLimit = 0; - TemplateBacktraceLimit = 0; - MacroBacktraceLimit = 0; + TemplateBacktraceLimit = DefaultTemplateBacktraceLimit; + MacroBacktraceLimit = DefaultMacroBacktraceLimit; } }; diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h index 6693ddbac57d..73d892105f21 100644 --- a/include/clang/Frontend/DocumentXML.h +++ b/include/clang/Frontend/DocumentXML.h @@ -114,6 +114,7 @@ private: void addPtrAttribute(const char* pName, const NamedDecl* D); void addPtrAttribute(const char* pName, const DeclContext* D); void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation + void addPtrAttribute(const char* pName, const NestedNameSpecifier* N); void addPtrAttribute(const char* pName, const LabelStmt* L); void addPtrAttribute(const char* pName, const char* text); @@ -145,12 +146,23 @@ inline void DocumentXML::initialize(ASTContext &Context) { //--------------------------------------------------------- template<class T> inline void DocumentXML::addAttribute(const char* pName, const T& value) { - Out << ' ' << pName << "=\"" << value << "\""; + std::string repr; + { + llvm::raw_string_ostream buf(repr); + buf << value; + buf.flush(); + } + + Out << ' ' << pName << "=\"" + << DocumentXML::escapeString(repr.c_str(), repr.size()) + << "\""; } //--------------------------------------------------------- inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) { - Out << ' ' << pName << "=\"" << text << "\""; + Out << ' ' << pName << "=\"" + << DocumentXML::escapeString(text, strlen(text)) + << "\""; } //--------------------------------------------------------- diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 3ddd77dc39e0..cee1c1d2be77 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -75,12 +75,10 @@ protected: }; class FixItAction : public ASTFrontendAction { -private: +protected: llvm::OwningPtr<FixItRewriter> Rewriter; llvm::OwningPtr<FixItPathRewriter> PathRewriter; -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile); @@ -133,6 +131,12 @@ public: virtual bool hasCodeCompletionSupport() const { return true; } }; +class BoostConAction : public SyntaxOnlyAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + /** * \brief Frontend action adaptor that merges ASTs together. * diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 60512edd6c1f..c43e68000952 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -23,13 +23,15 @@ namespace frontend { ASTPrint, ///< Parse ASTs and print them. ASTPrintXML, ///< Parse ASTs and print them in XML. ASTView, ///< Parse ASTs and view them in Graphviz. + BoostCon, ///< BoostCon mode. DumpRawTokens, ///< Dump out raw tokens. DumpTokens, ///< Dump out preprocessed tokens. EmitAssembly, ///< Emit a .s file. EmitBC, ///< Emit a .bc file. EmitHTML, ///< Translate input source into HTML. EmitLLVM, ///< Emit a .ll file. - EmitLLVMOnly, ///< Generate LLVM IR, but do not + EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything. + EmitCodeGenOnly, ///< Generate machine code, but don't emit anything. EmitObj, ///< Emit a .o file. FixIt, ///< Parse and apply any fixits to the source. GeneratePCH, ///< Generate pre-compiled header. @@ -77,6 +79,8 @@ public: unsigned ShowHelp : 1; ///< Show the -help text. unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion /// results. + unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code + /// completion results. unsigned ShowStats : 1; ///< Show frontend performance /// metrics and statistics. unsigned ShowTimers : 1; ///< Show timers for individual @@ -123,6 +127,7 @@ public: RelocatablePCH = 0; ShowHelp = 0; ShowMacrosInCodeCompletion = 0; + ShowCodePatternsInCodeCompletion = 0; ShowStats = 0; ShowTimers = 0; ShowVersion = 0; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 1640afb4122a..2493cfd47d1e 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -415,7 +415,9 @@ namespace clang { /// \brief An UnresolvedUsingType record. TYPE_UNRESOLVED_USING = 26, /// \brief An InjectedClassNameType record. - TYPE_INJECTED_CLASS_NAME = 27 + TYPE_INJECTED_CLASS_NAME = 27, + /// \brief An ObjCObjectType record. + TYPE_OBJC_OBJECT = 28 }; /// \brief The type IDs for special types constructed by semantic @@ -534,8 +536,46 @@ namespace clang { /// IDs. This data is used when performing qualified name lookup /// into a DeclContext via DeclContext::lookup. DECL_CONTEXT_VISIBLE, - /// \brief A NamespaceDecl record. - DECL_NAMESPACE + /// \brief A NamespaceDecl rcord. + DECL_NAMESPACE, + /// \brief A NamespaceAliasDecl record. + DECL_NAMESPACE_ALIAS, + /// \brief A UsingDecl record. + DECL_USING, + /// \brief A UsingShadowDecl record. + DECL_USING_SHADOW, + /// \brief A UsingDirecitveDecl record. + DECL_USING_DIRECTIVE, + /// \brief An UnresolvedUsingValueDecl record. + DECL_UNRESOLVED_USING_VALUE, + /// \brief An UnresolvedUsingTypenameDecl record. + DECL_UNRESOLVED_USING_TYPENAME, + /// \brief A LinkageSpecDecl record. + DECL_LINKAGE_SPEC, + /// \brief A CXXRecordDecl record. + DECL_CXX_RECORD, + /// \brief A CXXMethodDecl record. + DECL_CXX_METHOD, + /// \brief A CXXConstructorDecl record. + DECL_CXX_CONSTRUCTOR, + /// \brief A CXXDestructorDecl record. + DECL_CXX_DESTRUCTOR, + /// \brief A CXXConversionDecl record. + DECL_CXX_CONVERSION, + + // FIXME: Implement serialization for these decl types. This just + // allocates the order in which + DECL_FRIEND, + DECL_FRIEND_TEMPLATE, + DECL_TEMPLATE, + DECL_CLASS_TEMPLATE, + DECL_CLASS_TEMPLATE_SPECIALIZATION, + DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, + DECL_FUNCTION_TEMPLATE, + DECL_TEMPLATE_TYPE_PARM, + DECL_NON_TYPE_TEMPLATE_PARM, + DECL_TEMPLATE_TEMPLATE_PARM, + DECL_STATIC_ASSERT }; /// \brief Record codes for each kind of statement or expression. @@ -692,6 +732,8 @@ namespace clang { /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, + /// \brief A CXXMemberCallExpr record. + EXPR_CXX_MEMBER_CALL, /// \brief A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, // \brief A CXXStaticCastExpr record. @@ -706,8 +748,18 @@ namespace clang { EXPR_CXX_FUNCTIONAL_CAST, // \brief A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, - // \brief A CXXNullPtrLiteralExpr record. - EXPR_CXX_NULL_PTR_LITERAL + EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr + EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr). + EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type). + EXPR_CXX_THIS, // CXXThisExpr + EXPR_CXX_THROW, // CXXThrowExpr + EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr + EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr + // + EXPR_CXX_ZERO_INIT_VALUE, // CXXZeroInitValueExpr + EXPR_CXX_NEW, // CXXNewExpr + + EXPR_CXX_EXPR_WITH_TEMPORARIES // CXXExprWithTemporaries }; /// \brief The kinds of designators that can occur in a diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index c2352301caa0..e144738236ea 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -52,6 +52,9 @@ class ASTContext; class Attr; class Decl; class DeclContext; +class NestedNameSpecifier; +class CXXBaseSpecifier; +class CXXBaseOrMemberInitializer; class GotoStmt; class LabelStmt; class MacroDefinition; @@ -649,8 +652,8 @@ public: /// declarations with this name are visible from translation unit scope, their /// declarations will be deserialized and introduced into the declaration /// chain of the identifier. - virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd); - IdentifierInfo* get(llvm::StringRef Name) { + virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd); + IdentifierInfo *get(llvm::StringRef Name) { return get(Name.begin(), Name.end()); } @@ -694,8 +697,21 @@ public: Selector GetSelector(const RecordData &Record, unsigned &Idx) { return DecodeSelector(Record[Idx++]); } + + /// \brief Read a declaration name. DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx); + NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record, + unsigned &Idx); + + /// \brief Read a source location. + SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) { + return SourceLocation::getFromRawEncoding(Record[Idx++]); + } + + /// \brief Read a source range. + SourceRange ReadSourceRange(const RecordData &Record, unsigned& Idx); + /// \brief Read an integral value llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx); @@ -708,6 +724,8 @@ public: // \brief Read a string std::string ReadString(const RecordData &Record, unsigned &Idx); + CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); + /// \brief Reads attributes from the current stream position. Attr *ReadAttributes(); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index e006de524ca3..85f53b9e0302 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -32,6 +32,9 @@ namespace llvm { namespace clang { class ASTContext; +class NestedNameSpecifier; +class CXXBaseSpecifier; +class CXXBaseOrMemberInitializer; class LabelStmt; class MacroDefinition; class MemorizeStatCalls; @@ -251,6 +254,9 @@ public: /// \brief Emit a source location. void AddSourceLocation(SourceLocation Loc, RecordData &Record); + /// \brief Emit a source range. + void AddSourceRange(SourceRange Range, RecordData &Record); + /// \brief Emit an integral value. void AddAPInt(const llvm::APInt &Value, RecordData &Record); @@ -260,12 +266,15 @@ public: /// \brief Emit a floating-point value. void AddAPFloat(const llvm::APFloat &Value, RecordData &Record); - /// \brief Emit a reference to an identifier + /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record); - /// \brief Emit a Selector (which is a smart pointer reference) - void AddSelectorRef(const Selector, RecordData &Record); + /// \brief Emit a Selector (which is a smart pointer reference). + void AddSelectorRef(Selector, RecordData &Record); + /// \brief Emit a CXXTemporary. + void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record); + /// \brief Get the unique number used to refer to the given /// identifier. pch::IdentID getIdentifierRef(const IdentifierInfo *II); @@ -304,6 +313,9 @@ public: /// \brief Emit a declaration name. void AddDeclarationName(DeclarationName Name, RecordData &Record); + /// \brief Emit a nested name specifier. + void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordData &Record); + /// \brief Add a string to the given record. void AddString(const std::string &Str, RecordData &Record); diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index 3add99a941c4..069d718d9def 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -61,6 +61,10 @@ # define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") #endif +NODE_XML(Type, "FIXME_Type") + ID_ATTRIBUTE_XML + ATTRIBUTE_XML(getTypeClassName(), "unhandled_type_name") +END_NODE_XML NODE_XML(QualType, "CvQualifiedType") ID_ATTRIBUTE_XML @@ -207,9 +211,9 @@ NODE_XML(RecordType, "Record") ID_ATTRIBUTE_XML ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind") - ENUM_XML(TagDecl::TK_struct, "struct") - ENUM_XML(TagDecl::TK_union, "union") - ENUM_XML(TagDecl::TK_class, "class") + ENUM_XML(TTK_Struct, "struct") + ENUM_XML(TTK_Union, "union") + ENUM_XML(TTK_Class, "class") END_ENUM_XML CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) END_NODE_XML @@ -228,11 +232,23 @@ NODE_XML(TemplateSpecializationType, "TemplateSpecializationType") ID_ATTRIBUTE_XML END_NODE_XML -NODE_XML(QualifiedNameType, "QualifiedNameType") +NODE_XML(ElaboratedType, "ElaboratedType") ID_ATTRIBUTE_XML + ATTRIBUTE_ENUM_XML(getKeyword(), "keyword") + ENUM_XML(ETK_None, "none") + ENUM_XML(ETK_Typename, "typename") + ENUM_XML(ETK_Struct, "struct") + ENUM_XML(ETK_Union, "union") + ENUM_XML(ETK_Class, "class") + ENUM_XML(ETK_Enum, "enum") + END_ENUM_XML TYPE_ATTRIBUTE_XML(getNamedType()) END_NODE_XML +NODE_XML(InjectedClassNameType, "InjectedClassNameType") + ID_ATTRIBUTE_XML +END_NODE_XML + NODE_XML(DependentNameType, "DependentNameType") ID_ATTRIBUTE_XML END_NODE_XML @@ -245,6 +261,29 @@ NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType") ID_ATTRIBUTE_XML END_NODE_XML +NODE_XML(SubstTemplateTypeParmType, "SubstTemplateTypeParm") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentSizedExtVectorType, "DependentSizedExtVector") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(UnresolvedUsingType, "UnresolvedUsing") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentTypeOfExprType, "DependentTypeOfExpr") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DecltypeType, "Decltype") + ID_ATTRIBUTE_XML +END_NODE_XML + +NODE_XML(DependentDecltypeType, "DependentDecltype") + ID_ATTRIBUTE_XML +END_NODE_XML //===----------------------------------------------------------------------===// #undef NODE_XML diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 2334d728f6e3..ba46fb18a68a 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -147,7 +147,7 @@ class StringLiteralParser { char *ResultPtr; // cursor public: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, - Preprocessor &PP); + Preprocessor &PP, bool Complain = true); bool hadError; bool AnyWide; bool Pascal; @@ -164,7 +164,7 @@ public: /// specified byte of the string data represented by Token. This handles /// advancing over escape sequences in the string. static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo, - Preprocessor &PP); + Preprocessor &PP, bool Complain = true); }; } // end namespace clang diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 20d9fc50e49f..f01b3afc45f5 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -290,8 +290,8 @@ public: /// 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 + /// 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; @@ -753,9 +753,9 @@ public: /// #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. + /// 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::SmallString<128> &FilenameBuffer); private: @@ -900,8 +900,6 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); - // HandleAssertDirective(Token &Tok); - // HandleUnassertDirective(Token &Tok); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/include/clang/Makefile b/include/clang/Makefile index d76e0a9c63ba..6abe375d5e97 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -1,5 +1,5 @@ LEVEL = ../../../.. -DIRS := Basic Driver +DIRS := AST Basic Driver include $(LEVEL)/Makefile.common @@ -10,7 +10,7 @@ install-local:: cd $(PROJ_SRC_ROOT)/tools/clang/include && \ for hdr in `find clang -type f '!' '(' -name '*~' \ -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ - -o -name 'Makefile' -o -name '*.td' ')' -print \ + -o -name 'Makefile' -o -name '*.td' -o -name '*.orig' ')' -print \ | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \ if test \! -d "$$instdir" ; then \ diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 3d68d80ef9f0..e21da81a8aa8 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -105,12 +105,19 @@ public: class FullExprArg { public: + FullExprArg(ActionBase &actions) : Expr(actions) { } + // FIXME: The const_cast here is ugly. RValue references would make this // much nicer (or we could duplicate a bunch of the move semantics // emulation code from Ownership.h). FullExprArg(const FullExprArg& Other) : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {} + FullExprArg &operator=(const FullExprArg& Other) { + Expr.operator=(move(const_cast<FullExprArg&>(Other).Expr)); + return *this; + } + OwningExprResult release() { return move(Expr); } @@ -279,13 +286,18 @@ public: /// \param Template if the name does refer to a template, the declaration /// of the template that the name refers to. /// + /// \param MemberOfUnknownSpecialization Will be set true if the resulting + /// member would be a member of an unknown specialization, in which case this + /// lookup cannot possibly pass at this time. + /// /// \returns the kind of template that this name refers to. virtual TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, - TemplateTy &Template) = 0; + TemplateTy &Template, + bool &MemberOfUnknownSpecialization) = 0; /// \brief Action called as part of error recovery when the parser has /// determined that the given name must refer to a template, but @@ -566,7 +578,9 @@ public: /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. - virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { + virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, + AccessSpecifier Access, + DeclSpec &DS) { return DeclPtrTy(); } @@ -826,21 +840,19 @@ public: /// \brief Parsed the start of a "switch" statement. /// + /// \param SwitchLoc The location of the "switch" keyword. + /// /// \param Cond if the "switch" condition was parsed as an expression, /// the expression itself. /// /// \param CondVar if the "switch" condition was parsed as a condition /// variable, the condition variable itself. - virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, + ExprArg Cond, DeclPtrTy CondVar) { return StmtEmpty(); } - /// ActOnSwitchBodyError - This is called if there is an error parsing the - /// body of the switch stmt instead of ActOnFinishSwitchStmt. - virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, - StmtArg Body) {} - virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { return StmtEmpty(); @@ -1609,6 +1621,22 @@ public: return DeclResult(); } + /// \brief Parsed an expression that will be handled as the condition in + /// an if/while/for statement. + /// + /// This routine handles the conversion of the expression to 'bool'. + /// + /// \param S The scope in which the expression occurs. + /// + /// \param Loc The location of the construct that requires the conversion to + /// a boolean value. + /// + /// \param SubExpr The expression that is being converted to bool. + virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, + ExprArg SubExpr) { + return move(SubExpr); + } + /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the /// new was qualified (::new). In a full new like /// @code new (p1, p2) type(c1, c2) @endcode @@ -2303,6 +2331,7 @@ public: } // ActOnPropertyImplDecl - called for every property implementation virtual DeclPtrTy ActOnPropertyImplDecl( + Scope *S, SourceLocation AtLoc, // location of the @synthesize/@dynamic SourceLocation PropertyNameLoc, // location for the property name bool ImplKind, // true for @synthesize, false for @@ -2346,7 +2375,7 @@ public: // protocols, categories), the parser passes all methods/properties. // For class implementations, these values default to 0. For implementations, // methods are processed incrementally (by ActOnMethodDeclaration above). - virtual void ActOnAtEnd(SourceRange AtEnd, + virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd, DeclPtrTy classDecl, DeclPtrTy *allMethods = 0, unsigned allNum = 0, @@ -2535,6 +2564,21 @@ public: //===---------------------------- Pragmas -------------------------------===// + enum PragmaOptionsAlignKind { + POAK_Natural, // #pragma options align=natural + POAK_Power, // #pragma options align=power + POAK_Mac68k, // #pragma options align=mac68k + POAK_Reset // #pragma options align=reset + }; + + /// ActOnPragmaOptionsAlign - Called on well formed #pragma options + /// align={...}. + virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc, + SourceLocation KindLoc) { + return; + } + enum PragmaPackKind { PPK_Default, // #pragma pack([n]) PPK_Show, // #pragma pack(show), only supported by MSVC. @@ -2620,9 +2664,13 @@ public: /// \brief Code completion occurs at the beginning of the /// initialization statement (or expression) in a for loop. CCC_ForInit, - /// \brief Code completion ocurs within the condition of an if, + /// \brief Code completion occurs within the condition of an if, /// while, switch, or for statement. - CCC_Condition + CCC_Condition, + /// \brief Code completion occurs within the body of a function on a + /// recovery path, where we do not have a specific handle on our position + /// in the grammar. + CCC_RecoveryInFunction }; /// \brief Code completion for an ordinary name that occurs within the given @@ -3003,7 +3051,9 @@ public: UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, - TemplateTy &Template); + TemplateTy &Template, + bool &MemberOfUnknownSpecialization); + /// ActOnDeclarator - If this is a typedef declarator, we modify the /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 12512f33c761..1e6d3ab9760d 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -55,6 +55,7 @@ public: enum Kind { // Please keep this list alphabetized. AT_IBAction, // Clang-specific. AT_IBOutlet, // Clang-specific. + AT_IBOutletCollection, // Clang-specific. AT_address_space, AT_alias, AT_aligned, @@ -102,6 +103,7 @@ public: AT_section, AT_sentinel, AT_stdcall, + AT_thiscall, AT_transparent_union, AT_unavailable, AT_unused, diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h index 5eb9635f06a1..e9a20b7872b5 100644 --- a/include/clang/Parse/Ownership.h +++ b/include/clang/Parse/Ownership.h @@ -166,7 +166,7 @@ namespace llvm { // conversions. // Flip this switch to measure performance impact of the smart pointers. -//#define DISABLE_SMART_POINTERS +// #define DISABLE_SMART_POINTERS namespace llvm { template<> @@ -403,8 +403,10 @@ namespace clang { friend class moving::ASTResultMover<Destroyer>; +#if !(defined(_MSC_VER) && _MSC_VER >= 1600) ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT +#endif void destroy() { if (Ptr) { @@ -444,6 +446,19 @@ namespace clang { return *this; } +#if defined(_MSC_VER) && _MSC_VER >= 1600 + // Emulated move semantics don't work with msvc. + ASTOwningResult(ASTOwningResult &&mover) + : ActionInv(mover.ActionInv), + Ptr(mover.Ptr) { + mover.Ptr = 0; + } + ASTOwningResult &operator=(ASTOwningResult &&mover) { + *this = moving::ASTResultMover<Destroyer>(mover); + return *this; + } +#endif + /// Assignment from a raw pointer. Takes ownership - beware! ASTOwningResult &operator=(void *raw) { destroy(); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 42a41d6d3028..8081c2492b2f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -110,6 +110,7 @@ class Parser { IdentifierInfo *Ident_vector; IdentifierInfo *Ident_pixel; + llvm::OwningPtr<PragmaHandler> OptionsHandler; llvm::OwningPtr<PragmaHandler> PackHandler; llvm::OwningPtr<PragmaHandler> UnusedHandler; llvm::OwningPtr<PragmaHandler> WeakHandler; @@ -234,6 +235,11 @@ private: assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && !isTokenBrace() && "Should consume special tokens with Consume*Token"); + if (Tok.is(tok::code_completion)) { + CodeCompletionRecovery(); + return ConsumeCodeCompletionToken(); + } + PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); return PrevTokLocation; @@ -308,6 +314,22 @@ private: return PrevTokLocation; } + /// \brief Consume the current code-completion token. + /// + /// This routine should be called to consume the code-completion token once + /// a code-completion action has already been invoked. + SourceLocation ConsumeCodeCompletionToken() { + assert(Tok.is(tok::code_completion)); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + ///\ brief When we are consuming a code-completion token within having + /// matched specific position in the grammar, provide code-completion results + /// based on context. + void CodeCompletionRecovery(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. @@ -1004,7 +1026,8 @@ private: //===--------------------------------------------------------------------===// // C++ if/switch/while condition expression. - bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult); + bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult, + SourceLocation Loc, bool ConvertToBoolean); //===--------------------------------------------------------------------===// // C++ types @@ -1060,7 +1083,9 @@ private: bool isStmtExpr = false); OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); bool ParseParenExprOrCondition(OwningExprResult &ExprResult, - DeclPtrTy &DeclResult); + DeclPtrTy &DeclResult, + SourceLocation Loc, + bool ConvertToBoolean); OwningStmtResult ParseIfStatement(AttributeList *Attr); OwningStmtResult ParseSwitchStatement(AttributeList *Attr); OwningStmtResult ParseWhileStatement(AttributeList *Attr); @@ -1348,6 +1373,8 @@ private: AttributeList *AttrList = 0, bool RequiresArg = false); void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, + IdentifierInfo *FirstIdent, + SourceLocation FirstIdentLoc, Declarator &D); void ParseBracketDeclarator(Declarator &D); @@ -1403,7 +1430,8 @@ private: bool EnteringContext, TypeTy *ObjectType, UnqualifiedId &Id, - bool AssumeTemplateId = false); + bool AssumeTemplateId, + SourceLocation TemplateKWLoc); bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, TypeTy *ObjectType, UnqualifiedId &Result); @@ -1457,6 +1485,7 @@ private: SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h index d7a0e3583ca5..023f40d3957c 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Parse/Scope.h @@ -74,7 +74,7 @@ public: /// It always has FnScope and DeclScope set as well. ObjCMethodScope = 0x400, - /// ElseScope - This scoep corresponds to an 'else' scope of an if/then/else + /// ElseScope - This scope corresponds to an 'else' scope of an if/then/else /// statement. ElseScope = 0x800 }; diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 348917a7d034..1f1c0cc11325 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -24,6 +24,41 @@ class raw_ostream; namespace clang { +/// \brief Default priority values for code-completion results based +/// on their kind. +enum { + /// \brief Priority for a declaration that is in the local scope. + CCP_LocalDeclaration = 8, + /// \brief Priority for a member declaration found from the current + /// method or member function. + CCP_MemberDeclaration = 20, + /// \brief Priority for a language keyword (that isn't any of the other + /// categories). + CCP_Keyword = 30, + /// \brief Priority for a code pattern. + CCP_CodePattern = 30, + /// \brief Priority for a type. + CCP_Type = 40, + /// \brief Priority for a non-type declaration. + CCP_Declaration = 50, + /// \brief Priority for a constant value (e.g., enumerator). + CCP_Constant = 60, + /// \brief Priority for a preprocessor macro. + CCP_Macro = 70, + /// \brief Priority for a nested-name-specifier. + CCP_NestedNameSpecifier = 75, + /// \brief Priority for a result that isn't likely to be what the user wants, + /// but is included for completeness. + CCP_Unlikely = 80 +}; + +/// \brief Priority value deltas that are applied to code-completion results +/// based on the context of the result. +enum { + /// \brief The result is in a base class. + CCD_InBaseClass = 2 +}; + class FunctionDecl; class FunctionType; class FunctionTemplateDecl; @@ -156,13 +191,14 @@ private: public: CodeCompletionString() { } - ~CodeCompletionString(); + ~CodeCompletionString() { clear(); } typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator; iterator begin() const { return Chunks.begin(); } iterator end() const { return Chunks.end(); } bool empty() const { return Chunks.empty(); } unsigned size() const { return Chunks.size(); } + void clear(); Chunk &operator[](unsigned I) { assert(I < size() && "Chunk index out-of-range"); @@ -232,8 +268,9 @@ public: void Serialize(llvm::raw_ostream &OS) const; /// \brief Deserialize a code-completion string from the given string. - static CodeCompletionString *Deserialize(const char *&Str, - const char *StrEnd); + /// + /// \returns true if successful, false otherwise. + bool Deserialize(const char *&Str, const char *StrEnd); }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, @@ -246,6 +283,10 @@ protected: /// \brief Whether to include macros in the code-completion results. bool IncludeMacros; + /// \brief Whether to include code patterns (such as for loops) within + /// the completion results. + bool IncludeCodePatterns; + /// \brief Whether the output format for the code-completion consumer is /// binary. bool OutputIsBinary; @@ -280,8 +321,11 @@ public: /// \brief When Kind == RK_Macro, the identifier that refers to a macro. IdentifierInfo *Macro; }; - - /// \brief Specifiers which parameter (of a function, Objective-C method, + + /// \brief The priority of this particular code-completion result. + unsigned Priority; + + /// \brief Specifies which parameter (of a function, Objective-C method, /// macro, etc.) we should start with when formatting the result. unsigned StartParameter; @@ -309,29 +353,30 @@ public: NestedNameSpecifier *Qualifier = 0, bool QualifierIsInformative = false) : Kind(RK_Declaration), Declaration(Declaration), - StartParameter(0), Hidden(false), - QualifierIsInformative(QualifierIsInformative), + Priority(getPriorityFromDecl(Declaration)), StartParameter(0), + Hidden(false), QualifierIsInformative(QualifierIsInformative), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - Qualifier(Qualifier) { } + Qualifier(Qualifier) { + } /// \brief Build a result that refers to a keyword or symbol. - Result(const char *Keyword) - : Kind(RK_Keyword), Keyword(Keyword), StartParameter(0), - Hidden(false), QualifierIsInformative(0), + Result(const char *Keyword, unsigned Priority = CCP_Keyword) + : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), + StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), Qualifier(0) { } /// \brief Build a result that refers to a macro. - Result(IdentifierInfo *Macro) - : Kind(RK_Macro), Macro(Macro), StartParameter(0), + Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) + : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), Qualifier(0) { } /// \brief Build a result that refers to a pattern. - Result(CodeCompletionString *Pattern) - : Kind(RK_Pattern), Pattern(Pattern), StartParameter(0), - Hidden(false), QualifierIsInformative(0), + Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern) + : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), + StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), Qualifier(0) { } @@ -352,6 +397,9 @@ public: CodeCompletionString *CreateCodeCompletionString(Sema &S); void Destroy(); + + /// brief Determine a base priority for the given declaration. + static unsigned getPriorityFromDecl(NamedDecl *ND); }; class OverloadCandidate { @@ -420,12 +468,17 @@ public: CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { } - CodeCompleteConsumer(bool IncludeMacros, bool OutputIsBinary) - : IncludeMacros(IncludeMacros), OutputIsBinary(OutputIsBinary) { } + CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + bool OutputIsBinary) + : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), + OutputIsBinary(OutputIsBinary) { } /// \brief Whether the code-completion consumer wants to see macros. bool includeMacros() const { return IncludeMacros; } + /// \brief Whether the code-completion consumer wants to see code patterns. + bool includeCodePatterns() const { return IncludeCodePatterns; } + /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } @@ -461,9 +514,9 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. - PrintingCodeCompleteConsumer(bool IncludeMacros, + PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, false), OS(OS) { } + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {} /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, @@ -484,8 +537,9 @@ public: /// \brief Create a new CIndex code-completion consumer that prints its /// results to the given raw output stream in a format readable to the CIndex /// library. - CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, true), OS(OS) { } + CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {} /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index eea727deb44d..851f8d1c68bf 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/Builtins.h" @@ -27,7 +28,6 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "RecordLayoutBuilder.h" using namespace clang; @@ -46,7 +46,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), - BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts), + BuiltinInfo(builtins), + DeclarationNames(*this), + ExternalSource(0), PrintingPolicy(LOpts), LastSDM(0, 0) { ObjCIdRedefinitionType = QualType(); ObjCClassRedefinitionType = QualType(); @@ -61,6 +63,12 @@ ASTContext::~ASTContext() { // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); + if (!FreeMemory) { + // Call all of the deallocation functions. + for (unsigned I = 0, N = Deallocations.size(); I != N; ++I) + Deallocations[I].first(Deallocations[I].second); + } + // Release all of the memory associated with overridden C++ methods. for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end(); @@ -111,6 +119,10 @@ ASTContext::~ASTContext() { TUDecl->Destroy(*this); } +void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { + Deallocations.push_back(std::make_pair(Callback, Data)); +} + void ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) { ExternalSource.reset(Source.take()); @@ -419,6 +431,18 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { return CharUnits::fromQuantity(Align / Target.getCharWidth()); } +std::pair<CharUnits, CharUnits> +ASTContext::getTypeInfoInChars(const Type *T) { + std::pair<uint64_t, unsigned> Info = getTypeInfo(T); + return std::make_pair(CharUnits::fromQuantity(Info.first / getCharWidth()), + CharUnits::fromQuantity(Info.second / getCharWidth())); +} + +std::pair<CharUnits, CharUnits> +ASTContext::getTypeInfoInChars(QualType T) { + return getTypeInfoInChars(T.getTypePtr()); +} + /// getTypeSize - Return the size of the specified type, in bits. This method /// does not work on incomplete types. /// @@ -593,6 +617,8 @@ ASTContext::getTypeInfo(const Type *T) { Align = EltInfo.second; break; } + case Type::ObjCObject: + return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -624,10 +650,6 @@ ASTContext::getTypeInfo(const Type *T) { return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> getReplacementType().getTypePtr()); - case Type::Elaborated: - return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType() - .getTypePtr()); - case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) { @@ -650,8 +672,8 @@ ASTContext::getTypeInfo(const Type *T) { return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType() .getTypePtr()); - case Type::QualifiedName: - return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr()); + case Type::Elaborated: + return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr()); case Type::TemplateSpecialization: assert(getCanonicalType(T) != T && @@ -875,40 +897,6 @@ TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, return DI; } -/// getInterfaceLayoutImpl - Get or compute information about the -/// layout of the given interface. -/// -/// \param Impl - If given, also include the layout of the interface's -/// implementation. This may differ by including synthesized ivars. -const ASTRecordLayout & -ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, - const ObjCImplementationDecl *Impl) { - assert(!D->isForwardDecl() && "Invalid interface decl!"); - - // Look up this layout, if already laid out, return what we have. - ObjCContainerDecl *Key = - Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D; - if (const ASTRecordLayout *Entry = ObjCLayouts[Key]) - return *Entry; - - // Add in synthesized ivar count if laying out an implementation. - if (Impl) { - unsigned SynthCount = CountNonClassIvars(D); - // If there aren't any sythesized ivars then reuse the interface - // entry. Note we can't cache this because we simply free all - // entries later; however we shouldn't look up implementations - // frequently. - if (SynthCount == 0) - return getObjCLayout(D, 0); - } - - const ASTRecordLayout *NewEntry = - ASTRecordLayoutBuilder::ComputeLayout(*this, D, Impl); - ObjCLayouts[Key] = NewEntry; - - return *NewEntry; -} - const ASTRecordLayout & ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) { return getObjCLayout(D, 0); @@ -919,45 +907,6 @@ ASTContext::getASTObjCImplementationLayout(const ObjCImplementationDecl *D) { return getObjCLayout(D->getClassInterface(), D); } -/// getASTRecordLayout - Get or compute information about the layout of the -/// specified record (struct/union/class), which indicates its size and field -/// position information. -const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { - D = D->getDefinition(); - assert(D && "Cannot get layout of forward declarations!"); - - // Look up this layout, if already laid out, return what we have. - // Note that we can't save a reference to the entry because this function - // is recursive. - const ASTRecordLayout *Entry = ASTRecordLayouts[D]; - if (Entry) return *Entry; - - const ASTRecordLayout *NewEntry = - ASTRecordLayoutBuilder::ComputeLayout(*this, D); - ASTRecordLayouts[D] = NewEntry; - - if (getLangOptions().DumpRecordLayouts) { - llvm::errs() << "\n*** Dumping AST Record Layout\n"; - DumpRecordLayout(D, llvm::errs()); - } - - return *NewEntry; -} - -const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { - RD = cast<CXXRecordDecl>(RD->getDefinition()); - assert(RD && "Cannot get key function for forward declarations!"); - - const CXXMethodDecl *&Entry = KeyFunctions[RD]; - if (!Entry) - Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD); - else - assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) && - "Key function changed!"); - - return Entry; -} - //===----------------------------------------------------------------------===// // Type creation/memoization methods //===----------------------------------------------------------------------===// @@ -1343,9 +1292,17 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, SourceRange Brackets) { // Since we don't unique expressions, it isn't possible to unique VLA's // that have an expression provided for their size. - + QualType CanonType; + + if (!EltTy.isCanonical()) { + if (NumElts) + NumElts->Retain(); + CanonType = getVariableArrayType(getCanonicalType(EltTy), NumElts, ASM, + EltTypeQuals, Brackets); + } + VariableArrayType *New = new(*this, TypeAlignment) - VariableArrayType(EltTy, QualType(), NumElts, ASM, EltTypeQuals, Brackets); + VariableArrayType(EltTy, CanonType, NumElts, ASM, EltTypeQuals, Brackets); VariableArrayTypes.push_back(New); Types.push_back(New); @@ -1694,10 +1651,6 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl)) return getTypedefType(Typedef); - if (const ObjCInterfaceDecl *ObjCInterface - = dyn_cast<ObjCInterfaceDecl>(Decl)) - return getObjCInterfaceType(ObjCInterface); - assert(!isa<TemplateTypeParmDecl>(Decl) && "Template type parameter types are always available."); @@ -1888,29 +1841,28 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, } QualType -ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS, - QualType NamedType) { +ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType) { llvm::FoldingSetNodeID ID; - QualifiedNameType::Profile(ID, NNS, NamedType); + ElaboratedType::Profile(ID, Keyword, NNS, NamedType); void *InsertPos = 0; - QualifiedNameType *T - = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos); + ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); QualType Canon = NamedType; if (!Canon.isCanonical()) { Canon = getCanonicalType(NamedType); - QualifiedNameType *CheckT - = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckT && "Qualified name canonical type broken"); + ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CheckT && "Elaborated canonical type broken"); (void)CheckT; } - T = new (*this) QualifiedNameType(NNS, NamedType, Canon); + T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon); Types.push_back(T); - QualifiedNameTypes.InsertNode(T, InsertPos); + ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0); } @@ -1987,30 +1939,6 @@ ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, return QualType(T, 0); } -QualType -ASTContext::getElaboratedType(QualType UnderlyingType, - ElaboratedType::TagKind Tag) { - llvm::FoldingSetNodeID ID; - ElaboratedType::Profile(ID, UnderlyingType, Tag); - - void *InsertPos = 0; - ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); - if (T) - return QualType(T, 0); - - QualType Canon = UnderlyingType; - if (!Canon.isCanonical()) { - Canon = getCanonicalType(Canon); - ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckT && "Elaborated canonical type is broken"); (void)CheckT; - } - - T = new (*this) ElaboratedType(UnderlyingType, Tag, Canon); - Types.push_back(T); - ElaboratedTypes.InsertNode(T, InsertPos); - return QualType(T, 0); -} - /// CmpProtocolNames - Comparison predicate for sorting protocols /// alphabetically. static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, @@ -2018,7 +1946,7 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, return LHS->getDeclName() < RHS->getDeclName(); } -static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols, +static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) { if (NumProtocols == 0) return true; @@ -2040,96 +1968,98 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, NumProtocols = ProtocolsEnd-Protocols; } -/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for -/// the given interface decl and the conforming protocol list. -QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, - ObjCProtocolDecl **Protocols, - unsigned NumProtocols, - unsigned Quals) { - llvm::FoldingSetNodeID ID; - ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); - Qualifiers Qs = Qualifiers::fromCVRMask(Quals); +QualType ASTContext::getObjCObjectType(QualType BaseType, + ObjCProtocolDecl * const *Protocols, + unsigned NumProtocols) { + // If the base type is an interface and there aren't any protocols + // to add, then the interface type will do just fine. + if (!NumProtocols && isa<ObjCInterfaceType>(BaseType)) + return BaseType; + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols); void *InsertPos = 0; - if (ObjCObjectPointerType *QT = - ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) - return getQualifiedType(QualType(QT, 0), Qs); + if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(QT, 0); - // Sort the protocol list alphabetically to canonicalize it. + // Build the canonical type, which has the canonical base type and + // a sorted-and-uniqued list of protocols. QualType Canonical; - if (!InterfaceT.isCanonical() || - !areSortedAndUniqued(Protocols, NumProtocols)) { - if (!areSortedAndUniqued(Protocols, NumProtocols)) { + bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols); + if (!ProtocolsSorted || !BaseType.isCanonical()) { + if (!ProtocolsSorted) { llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols, Protocols + NumProtocols); unsigned UniqueCount = NumProtocols; SortAndUniqueProtocols(&Sorted[0], UniqueCount); - - Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), - &Sorted[0], UniqueCount); + Canonical = getObjCObjectType(getCanonicalType(BaseType), + &Sorted[0], UniqueCount); } else { - Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), - Protocols, NumProtocols); + Canonical = getObjCObjectType(getCanonicalType(BaseType), + Protocols, NumProtocols); } // Regenerate InsertPos. - ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); + ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos); } - // No match. - unsigned Size = sizeof(ObjCObjectPointerType) - + NumProtocols * sizeof(ObjCProtocolDecl *); + unsigned Size = sizeof(ObjCObjectTypeImpl); + Size += NumProtocols * sizeof(ObjCProtocolDecl *); void *Mem = Allocate(Size, TypeAlignment); - ObjCObjectPointerType *QType = new (Mem) ObjCObjectPointerType(Canonical, - InterfaceT, - Protocols, - NumProtocols); + ObjCObjectTypeImpl *T = + new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols); - Types.push_back(QType); - ObjCObjectPointerTypes.InsertNode(QType, InsertPos); - return getQualifiedType(QualType(QType, 0), Qs); + Types.push_back(T); + ObjCObjectTypes.InsertNode(T, InsertPos); + return QualType(T, 0); } -/// getObjCInterfaceType - Return the unique reference to the type for the -/// specified ObjC interface decl. The list of protocols is optional. -QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **Protocols, unsigned NumProtocols) { +/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for +/// the given object type. +QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) { llvm::FoldingSetNodeID ID; - ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols); + ObjCObjectPointerType::Profile(ID, ObjectT); void *InsertPos = 0; - if (ObjCInterfaceType *QT = - ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos)) + if (ObjCObjectPointerType *QT = + ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); - // Sort the protocol list alphabetically to canonicalize it. + // Find the canonical object type. QualType Canonical; - if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) { - llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols, - Protocols + NumProtocols); - - unsigned UniqueCount = NumProtocols; - SortAndUniqueProtocols(&Sorted[0], UniqueCount); + if (!ObjectT.isCanonical()) { + Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT)); - Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount); - - ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos); + // Regenerate InsertPos. + ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); } - unsigned Size = sizeof(ObjCInterfaceType) - + NumProtocols * sizeof(ObjCProtocolDecl *); - void *Mem = Allocate(Size, TypeAlignment); - ObjCInterfaceType *QType = new (Mem) ObjCInterfaceType(Canonical, - const_cast<ObjCInterfaceDecl*>(Decl), - Protocols, - NumProtocols); + // No match. + void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment); + ObjCObjectPointerType *QType = + new (Mem) ObjCObjectPointerType(Canonical, ObjectT); Types.push_back(QType); - ObjCInterfaceTypes.InsertNode(QType, InsertPos); + ObjCObjectPointerTypes.InsertNode(QType, InsertPos); return QualType(QType, 0); } +/// getObjCInterfaceType - Return the unique reference to the type for the +/// specified ObjC interface decl. The list of protocols is optional. +QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) { + if (Decl->TypeForDecl) + return QualType(Decl->TypeForDecl, 0); + + // FIXME: redeclarations? + void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); + ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl); + Decl->TypeForDecl = T; + Types.push_back(T); + return QualType(T, 0); +} + /// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique /// TypeOfExprType AST's (since expression's are never shared). For example, /// multiple declarations that refer to "typeof(x)" all contain different @@ -2362,26 +2292,35 @@ CanQualType ASTContext::getCanonicalType(QualType T) { QualType ASTContext::getUnqualifiedArrayType(QualType T, Qualifiers &Quals) { Quals = T.getQualifiers(); - if (!isa<ArrayType>(T)) { + const ArrayType *AT = getAsArrayType(T); + if (!AT) { return T.getUnqualifiedType(); } - const ArrayType *AT = cast<ArrayType>(T); QualType Elt = AT->getElementType(); QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals); if (Elt == UnqualElt) return T; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { return getConstantArrayType(UnqualElt, CAT->getSize(), CAT->getSizeModifier(), 0); } - if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) { + if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0); } - const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T); + if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) { + return getVariableArrayType(UnqualElt, + VAT->getSizeExpr() ? + VAT->getSizeExpr()->Retain() : 0, + VAT->getSizeModifier(), + VAT->getIndexTypeCVRQualifiers(), + VAT->getBracketsRange()); + } + + const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT); return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(), DSAT->getSizeModifier(), 0, SourceRange()); @@ -2716,6 +2655,9 @@ unsigned ASTContext::getIntegerRank(Type *T) { /// \returns the type this bit-field will promote to, or NULL if no /// promotion occurs. QualType ASTContext::isPromotableBitField(Expr *E) { + if (E->isTypeDependent() || E->isValueDependent()) + return QualType(); + FieldDecl *Field = E->getBitField(); if (!Field) return QualType(); @@ -2811,7 +2753,7 @@ CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, QualType ASTContext::getCFConstantStringType() { if (!CFConstantStringTypeDecl) { CFConstantStringTypeDecl = - CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get("NSConstantString")); CFConstantStringTypeDecl->startDefinition(); @@ -2853,7 +2795,7 @@ void ASTContext::setCFConstantStringType(QualType T) { QualType ASTContext::getNSConstantStringType() { if (!NSConstantStringTypeDecl) { NSConstantStringTypeDecl = - CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get("__builtin_NSString")); NSConstantStringTypeDecl->startDefinition(); @@ -2892,7 +2834,7 @@ void ASTContext::setNSConstantStringType(QualType T) { QualType ASTContext::getObjCFastEnumerationStateType() { if (!ObjCFastEnumerationStateTypeDecl) { ObjCFastEnumerationStateTypeDecl = - CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get("__objcFastEnumerationState")); ObjCFastEnumerationStateTypeDecl->startDefinition(); @@ -2927,7 +2869,7 @@ QualType ASTContext::getBlockDescriptorType() { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get("__block_descriptor")); T->startDefinition(); @@ -2972,7 +2914,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get("__block_descriptor_withcopydispose")); T->startDefinition(); @@ -3044,7 +2986,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { llvm::raw_svector_ostream(Name) << "__Block_byref_" << ++UniqueBlockByRefTypeID << '_' << DeclName; RecordDecl *T; - T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get(Name.str())); T->startDefinition(); QualType Int32Ty = IntTy; @@ -3088,14 +3030,15 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { QualType ASTContext::getBlockParmType( bool BlockHasCopyDispose, - llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { + llvm::SmallVectorImpl<const Expr *> &Layout) { + // FIXME: Move up static unsigned int UniqueBlockParmTypeID = 0; llvm::SmallString<36> Name; llvm::raw_svector_ostream(Name) << "__block_literal_" << ++UniqueBlockParmTypeID; RecordDecl *T; - T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), &Idents.get(Name.str())); T->startDefinition(); QualType FieldTypes[] = { @@ -3125,22 +3068,28 @@ QualType ASTContext::getBlockParmType( T->addDecl(Field); } - for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) { - const Expr *E = BlockDeclRefDecls[i]; - const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); - clang::IdentifierInfo *Name = 0; - if (BDRE) { + for (unsigned i = 0; i < Layout.size(); ++i) { + const Expr *E = Layout[i]; + + QualType FieldType = E->getType(); + IdentifierInfo *FieldName = 0; + if (isa<CXXThisExpr>(E)) { + FieldName = &Idents.get("this"); + } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) { const ValueDecl *D = BDRE->getDecl(); - Name = &Idents.get(D->getName()); + FieldName = D->getIdentifier(); + if (BDRE->isByRef()) + FieldType = BuildByRefType(D->getNameAsCString(), FieldType); + } else { + // Padding. + assert(isa<ConstantArrayType>(FieldType) && + isa<DeclRefExpr>(E) && + !cast<DeclRefExpr>(E)->getDecl()->getDeclName() && + "doesn't match characteristics of padding decl"); } - QualType FieldType = E->getType(); - - if (BDRE && BDRE->isByRef()) - FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(), - FieldType); FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - Name, FieldType, /*TInfo=*/0, + FieldName, FieldType, /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); Field->setAccess(AS_public); T->addDecl(Field); @@ -3593,6 +3542,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { S += II->getName(); + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size(), + (*this).PrintingPolicy); + + S += TemplateArgsStr; + } } else { S += '?'; } @@ -3636,6 +3596,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } + // Ignore protocol qualifiers when mangling at this level. + if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>()) + T = OT->getBaseType(); + if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { // @encode(class_name) ObjCInterfaceDecl *OI = OIT->getDecl(); @@ -3718,6 +3682,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } + // gcc just blithely ignores member pointers. + // TODO: maybe there should be a mangling for these + if (T->getAs<MemberPointerType>()) + return; + assert(0 && "@encode for type not implemented!"); } @@ -4106,18 +4075,21 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, /// bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT) { + const ObjCObjectType* LHS = LHSOPT->getObjectType(); + const ObjCObjectType* RHS = RHSOPT->getObjectType(); + // If either type represents the built-in 'id' or 'Class' types, return true. - if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType()) + if (LHS->isObjCUnqualifiedIdOrClass() || + RHS->isObjCUnqualifiedIdOrClass()) return true; - if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType()) + if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId()) return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0), QualType(RHSOPT,0), false); - const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); - const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); - if (LHS && RHS) // We have 2 user-defined types. + // If we have 2 user-defined types, fall into that path. + if (LHS->getInterface() && RHS->getInterface()) return canAssignObjCInterfaces(LHS, RHS); return false; @@ -4168,8 +4140,10 @@ void getIntersectionOfProtocols(ASTContext &Context, const ObjCObjectPointerType *RHSOPT, llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) { - const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); - const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); + const ObjCObjectType* LHS = LHSOPT->getObjectType(); + const ObjCObjectType* RHS = RHSOPT->getObjectType(); + assert(LHS->getInterface() && "LHS must have an interface base"); + assert(RHS->getInterface() && "RHS must have an interface base"); llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet; unsigned LHSNumProtocols = LHS->getNumProtocols(); @@ -4177,7 +4151,8 @@ void getIntersectionOfProtocols(ASTContext &Context, InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end()); else { llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols; - Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols); + Context.CollectInheritedProtocols(LHS->getInterface(), + LHSInheritedProtocols); InheritedProtocolSet.insert(LHSInheritedProtocols.begin(), LHSInheritedProtocols.end()); } @@ -4192,7 +4167,8 @@ void getIntersectionOfProtocols(ASTContext &Context, } else { llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols; - Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols); + Context.CollectInheritedProtocols(RHS->getInterface(), + RHSInheritedProtocols); for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = RHSInheritedProtocols.begin(), E = RHSInheritedProtocols.end(); I != E; ++I) @@ -4206,37 +4182,40 @@ void getIntersectionOfProtocols(ASTContext &Context, /// 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) + const ObjCObjectPointerType *Lptr, + const ObjCObjectPointerType *Rptr) { + const ObjCObjectType *LHS = Lptr->getObjectType(); + const ObjCObjectType *RHS = Rptr->getObjectType(); + const ObjCInterfaceDecl* LDecl = LHS->getInterface(); + const ObjCInterfaceDecl* RDecl = RHS->getInterface(); + if (!LDecl || !RDecl) return QualType(); - while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) { - QualType LHSTy = getObjCInterfaceType(LHSIDecl); - LHS = LHSTy->getAs<ObjCInterfaceType>(); + while ((LDecl = LDecl->getSuperClass())) { + LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl)); 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; + llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols; + getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols); + + QualType Result = QualType(LHS, 0); + if (!Protocols.empty()) + Result = getObjCObjectType(Result, Protocols.data(), Protocols.size()); + Result = getObjCObjectPointerType(Result); + return Result; } } return QualType(); } -bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, - const ObjCInterfaceType *RHS) { +bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, + const ObjCObjectType *RHS) { + assert(LHS->getInterface() && "LHS is not an interface type"); + assert(RHS->getInterface() && "RHS is not an interface type"); + // Verify that the base decls are compatible: the RHS must be a subclass of // the LHS. - if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl())) + if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface())) return false; // RHS must have a superset of the protocols in the LHS. If the LHS is not @@ -4249,15 +4228,15 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, if (RHS->getNumProtocols() == 0) return true; // FIXME: should return false! - for (ObjCInterfaceType::qual_iterator LHSPI = LHS->qual_begin(), - LHSPE = LHS->qual_end(); + for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), + LHSPE = LHS->qual_end(); LHSPI != LHSPE; LHSPI++) { bool RHSImplementsProtocol = false; // If the RHS doesn't implement the protocol on the left, the types // are incompatible. - for (ObjCInterfaceType::qual_iterator RHSPI = RHS->qual_begin(), - RHSPE = RHS->qual_end(); + for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(), + RHSPE = RHS->qual_end(); RHSPI != RHSPE; RHSPI++) { if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) { RHSImplementsProtocol = true; @@ -4483,6 +4462,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, if (RHSClass == Type::VariableArray || RHSClass == Type::IncompleteArray) RHSClass = Type::ConstantArray; + // ObjCInterfaces are just specialized ObjCObjects. + if (LHSClass == Type::ObjCInterface) LHSClass = Type::ObjCObject; + if (RHSClass == Type::ObjCInterface) RHSClass = Type::ObjCObject; + // Canonicalize ExtVector -> Vector. if (LHSClass == Type::ExtVector) LHSClass = Type::Vector; if (RHSClass == Type::ExtVector) RHSClass = Type::Vector; @@ -4522,6 +4505,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, assert(false && "C++ should never be in mergeTypes"); return QualType(); + case Type::ObjCInterface: case Type::IncompleteArray: case Type::VariableArray: case Type::FunctionProto: @@ -4614,14 +4598,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, RHSCan->getAs<VectorType>())) return LHS; return QualType(); - case Type::ObjCInterface: { - // Check if the interfaces are assignment compatible. + case Type::ObjCObject: { + // Check if the types are assignment compatible. // FIXME: This should be type compatibility, e.g. whether // "LHS x; RHS x;" at global scope is legal. - const ObjCInterfaceType* LHSIface = LHS->getAs<ObjCInterfaceType>(); - const ObjCInterfaceType* RHSIface = RHS->getAs<ObjCInterfaceType>(); - if (LHSIface && RHSIface && - canAssignObjCInterfaces(LHSIface, RHSIface)) + const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>(); + const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>(); + if (canAssignObjCInterfaces(LHSIface, RHSIface)) return LHS; return QualType(); @@ -4645,6 +4628,87 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return QualType(); } +/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and +/// 'RHS' attributes and returns the merged version; including for function +/// return types. +QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { + QualType LHSCan = getCanonicalType(LHS), + RHSCan = getCanonicalType(RHS); + // If two types are identical, they are compatible. + if (LHSCan == RHSCan) + return LHS; + if (RHSCan->isFunctionType()) { + if (!LHSCan->isFunctionType()) + return QualType(); + QualType OldReturnType = + cast<FunctionType>(RHSCan.getTypePtr())->getResultType(); + QualType NewReturnType = + cast<FunctionType>(LHSCan.getTypePtr())->getResultType(); + QualType ResReturnType = + mergeObjCGCQualifiers(NewReturnType, OldReturnType); + if (ResReturnType.isNull()) + return QualType(); + if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) { + // id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo(); + // In either case, use OldReturnType to build the new function type. + const FunctionType *F = LHS->getAs<FunctionType>(); + if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) { + FunctionType::ExtInfo Info = getFunctionExtInfo(LHS); + QualType ResultType + = getFunctionType(OldReturnType, FPT->arg_type_begin(), + FPT->getNumArgs(), FPT->isVariadic(), + FPT->getTypeQuals(), + FPT->hasExceptionSpec(), + FPT->hasAnyExceptionSpec(), + FPT->getNumExceptions(), + FPT->exception_begin(), + Info); + return ResultType; + } + } + return QualType(); + } + + // If the qualifiers are different, the types can still be merged. + Qualifiers LQuals = LHSCan.getLocalQualifiers(); + Qualifiers RQuals = RHSCan.getLocalQualifiers(); + if (LQuals != RQuals) { + // If any of these qualifiers are different, we have a type mismatch. + if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || + LQuals.getAddressSpace() != RQuals.getAddressSpace()) + return QualType(); + + // Exactly one GC qualifier difference is allowed: __strong is + // okay if the other type has no GC qualifier but is an Objective + // C object pointer (i.e. implicitly strong by default). We fix + // this by pretending that the unqualified type was actually + // qualified __strong. + Qualifiers::GC GC_L = LQuals.getObjCGCAttr(); + Qualifiers::GC GC_R = RQuals.getObjCGCAttr(); + assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements"); + + if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak) + return QualType(); + + if (GC_L == Qualifiers::Strong) + return LHS; + if (GC_R == Qualifiers::Strong) + return RHS; + return QualType(); + } + + if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) { + QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType ResQT = mergeObjCGCQualifiers(LHSBaseQT, RHSBaseQT); + if (ResQT == LHSBaseQT) + return LHS; + if (ResQT == RHSBaseQT) + return RHS; + } + return QualType(); +} + //===----------------------------------------------------------------------===// // Integer Predicates //===----------------------------------------------------------------------===// diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index e4cd2a9c1053..0d609bfa6d39 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -19,65 +19,41 @@ using namespace clang; -/// Determines whether we should have an a.k.a. clause when -/// pretty-printing a type. There are three main criteria: -/// -/// 1) Some types provide very minimal sugar that doesn't impede the -/// user's understanding --- for example, elaborated type -/// specifiers. If this is all the sugar we see, we don't want an -/// a.k.a. clause. -/// 2) Some types are technically sugared but are much more familiar -/// when seen in their sugared form --- for example, va_list, -/// vector types, and the magic Objective C types. We don't -/// want to desugar these, even if we do produce an a.k.a. clause. -/// 3) Some types may have already been desugared previously in this diagnostic. -/// if this is the case, doing another "aka" would just be clutter. -/// -static bool ShouldAKA(ASTContext &Context, QualType QT, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - QualType &DesugaredQT) { - QualType InputTy = QT; - - bool AKA = false; - QualifierCollector Qc; - +// Returns a desugared version of the QualType, and marks ShouldAKA as true +// whenever we remove significant sugar from the type. +static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { + QualifierCollector QC; + while (true) { - const Type *Ty = Qc.strip(QT); - + const Type *Ty = QC.strip(QT); + // Don't aka just because we saw an elaborated type... if (isa<ElaboratedType>(Ty)) { QT = cast<ElaboratedType>(Ty)->desugar(); continue; } - - // ...or a qualified name type... - if (isa<QualifiedNameType>(Ty)) { - QT = cast<QualifiedNameType>(Ty)->desugar(); - continue; - } // ...or a substituted template type parameter. if (isa<SubstTemplateTypeParmType>(Ty)) { QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); continue; } - + // Don't desugar template specializations. if (isa<TemplateSpecializationType>(Ty)) break; - + // Don't desugar magic Objective-C types. if (QualType(Ty,0) == Context.getObjCIdType() || QualType(Ty,0) == Context.getObjCClassType() || QualType(Ty,0) == Context.getObjCSelType() || QualType(Ty,0) == Context.getObjCProtoType()) break; - + // Don't desugar va_list. if (QualType(Ty,0) == Context.getBuiltinVaListType()) break; - + // Otherwise, do a single-step desugar. QualType Underlying; bool IsSugar = false; @@ -94,50 +70,56 @@ break; \ } #include "clang/AST/TypeNodes.def" } - + // If it wasn't sugared, we're done. if (!IsSugar) break; - + // If the desugared type is a vector type, we don't want to expand // it, it will turn into an attribute mess. People want their "vec4". if (isa<VectorType>(Underlying)) break; - + // Don't desugar through the primary typedef of an anonymous type. if (isa<TagType>(Underlying) && isa<TypedefType>(QT)) if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() == cast<TypedefType>(QT)->getDecl()) break; - - // Otherwise, we're tearing through something opaque; note that - // we'll eventually need an a.k.a. clause and keep going. - AKA = true; + + // Record that we actually looked through an opaque type here. + ShouldAKA = true; QT = Underlying; - continue; } - - // If we never tore through opaque sugar, don't print aka. - if (!AKA) return false; - - // If we did, check to see if we already desugared this type in this - // diagnostic. If so, don't do it again. - for (unsigned i = 0; i != NumPrevArgs; ++i) { - // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == Diagnostic::ak_qualtype) { - void *Ptr = (void*)PrevArgs[i].second; - QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); - if (PrevTy == InputTy) - return false; - } + + // If we have a pointer-like type, desugar the pointee as well. + // FIXME: Handle other pointer-like types. + if (const PointerType *Ty = QT->getAs<PointerType>()) { + QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); + } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { + QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); } - - DesugaredQT = Qc.apply(QT); - return true; + + return QC.apply(QT); } /// \brief Convert the given type to a string suitable for printing as part of -/// a diagnostic. +/// a diagnostic. +/// +/// There are three main criteria when determining whether we should have an +/// a.k.a. clause when pretty-printing a type: +/// +/// 1) Some types provide very minimal sugar that doesn't impede the +/// user's understanding --- for example, elaborated type +/// specifiers. If this is all the sugar we see, we don't want an +/// a.k.a. clause. +/// 2) Some types are technically sugared but are much more familiar +/// when seen in their sugared form --- for example, va_list, +/// vector types, and the magic Objective C types. We don't +/// want to desugar these, even if we do produce an a.k.a. clause. +/// 3) Some types may have already been desugared previously in this diagnostic. +/// if this is the case, doing another "aka" would just be clutter. /// /// \param Context the context in which the type was allocated /// \param Ty the type to print @@ -147,18 +129,35 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, unsigned NumPrevArgs) { // FIXME: Playing with std::string is really slow. std::string S = Ty.getAsString(Context.PrintingPolicy); - + + // Check to see if we already desugared this type in this + // diagnostic. If so, don't do it again. + bool Repeated = false; + for (unsigned i = 0; i != NumPrevArgs; ++i) { + // TODO: Handle ak_declcontext case. + if (PrevArgs[i].first == Diagnostic::ak_qualtype) { + void *Ptr = (void*)PrevArgs[i].second; + QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); + if (PrevTy == Ty) { + Repeated = true; + break; + } + } + } + // Consider producing an a.k.a. clause if removing all the direct // sugar gives us something "significantly different". - - QualType DesugaredTy; - if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) { - S = "'"+S+"' (aka '"; - S += DesugaredTy.getAsString(Context.PrintingPolicy); - S += "')"; - return S; + if (!Repeated) { + bool ShouldAKA = false; + QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); + if (ShouldAKA) { + S = "'"+S+"' (aka '"; + S += DesugaredTy.getAsString(Context.PrintingPolicy); + S += "')"; + return S; + } } - + S = "'" + S + "'"; return S; } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index ae09d7978ea5..6ed08d1e1e29 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -68,13 +68,13 @@ namespace { // FIXME: DependentDecltypeType QualType VisitRecordType(RecordType *T); QualType VisitEnumType(EnumType *T); - QualType VisitElaboratedType(ElaboratedType *T); // FIXME: TemplateTypeParmType // FIXME: SubstTemplateTypeParmType // FIXME: TemplateSpecializationType - QualType VisitQualifiedNameType(QualifiedNameType *T); + QualType VisitElaboratedType(ElaboratedType *T); // FIXME: DependentNameType QualType VisitObjCInterfaceType(ObjCInterfaceType *T); + QualType VisitObjCObjectType(ObjCObjectType *T); QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); // Importing declarations @@ -532,19 +532,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, cast<TagType>(T2)->getDecl())) return false; break; - - case Type::Elaborated: { - const ElaboratedType *Elab1 = cast<ElaboratedType>(T1); - const ElaboratedType *Elab2 = cast<ElaboratedType>(T2); - if (Elab1->getTagKind() != Elab2->getTagKind()) - return false; - if (!IsStructurallyEquivalent(Context, - Elab1->getUnderlyingType(), - Elab2->getUnderlyingType())) - return false; - break; - } - + case Type::TemplateTypeParm: { const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1); const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2); @@ -594,16 +582,19 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } - case Type::QualifiedName: { - const QualifiedNameType *Qual1 = cast<QualifiedNameType>(T1); - const QualifiedNameType *Qual2 = cast<QualifiedNameType>(T2); + case Type::Elaborated: { + const ElaboratedType *Elab1 = cast<ElaboratedType>(T1); + const ElaboratedType *Elab2 = cast<ElaboratedType>(T2); + // CHECKME: what if a keyword is ETK_None or ETK_typename ? + if (Elab1->getKeyword() != Elab2->getKeyword()) + return false; if (!IsStructurallyEquivalent(Context, - Qual1->getQualifier(), - Qual2->getQualifier())) + Elab1->getQualifier(), + Elab2->getQualifier())) return false; if (!IsStructurallyEquivalent(Context, - Qual1->getNamedType(), - Qual2->getNamedType())) + Elab1->getNamedType(), + Elab2->getNamedType())) return false; break; } @@ -642,12 +633,22 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Iface1->getDecl(), Iface2->getDecl())) return false; - if (Iface1->getNumProtocols() != Iface2->getNumProtocols()) + break; + } + + case Type::ObjCObject: { + const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1); + const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2); + if (!IsStructurallyEquivalent(Context, + Obj1->getBaseType(), + Obj2->getBaseType())) + return false; + if (Obj1->getNumProtocols() != Obj2->getNumProtocols()) return false; - for (unsigned I = 0, N = Iface1->getNumProtocols(); I != N; ++I) { + for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) { if (!IsStructurallyEquivalent(Context, - Iface1->getProtocol(I), - Iface2->getProtocol(I))) + Obj1->getProtocol(I), + Obj2->getProtocol(I))) return false; } break; @@ -660,14 +661,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Ptr1->getPointeeType(), Ptr2->getPointeeType())) return false; - if (Ptr1->getNumProtocols() != Ptr2->getNumProtocols()) - return false; - for (unsigned I = 0, N = Ptr1->getNumProtocols(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Ptr1->getProtocol(I), - Ptr2->getProtocol(I))) - return false; - } break; } @@ -1293,24 +1286,20 @@ QualType ASTNodeImporter::VisitEnumType(EnumType *T) { } QualType ASTNodeImporter::VisitElaboratedType(ElaboratedType *T) { - QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); - if (ToUnderlyingType.isNull()) - return QualType(); - - return Importer.getToContext().getElaboratedType(ToUnderlyingType, - T->getTagKind()); -} - -QualType ASTNodeImporter::VisitQualifiedNameType(QualifiedNameType *T) { - NestedNameSpecifier *ToQualifier = Importer.Import(T->getQualifier()); - if (!ToQualifier) - return QualType(); + NestedNameSpecifier *ToQualifier = 0; + // Note: the qualifier in an ElaboratedType is optional. + if (T->getQualifier()) { + ToQualifier = Importer.Import(T->getQualifier()); + if (!ToQualifier) + return QualType(); + } QualType ToNamedType = Importer.Import(T->getNamedType()); if (ToNamedType.isNull()) return QualType(); - return Importer.getToContext().getQualifiedNameType(ToQualifier, ToNamedType); + return Importer.getToContext().getElaboratedType(T->getKeyword(), + ToQualifier, ToNamedType); } QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { @@ -1319,8 +1308,16 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { if (!Class) return QualType(); + return Importer.getToContext().getObjCInterfaceType(Class); +} + +QualType ASTNodeImporter::VisitObjCObjectType(ObjCObjectType *T) { + QualType ToBaseType = Importer.Import(T->getBaseType()); + if (ToBaseType.isNull()) + return QualType(); + llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - for (ObjCInterfaceType::qual_iterator P = T->qual_begin(), + for (ObjCObjectType::qual_iterator P = T->qual_begin(), PEnd = T->qual_end(); P != PEnd; ++P) { ObjCProtocolDecl *Protocol @@ -1330,9 +1327,9 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { Protocols.push_back(Protocol); } - return Importer.getToContext().getObjCInterfaceType(Class, - Protocols.data(), - Protocols.size()); + return Importer.getToContext().getObjCObjectType(ToBaseType, + Protocols.data(), + Protocols.size()); } QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) { @@ -1340,20 +1337,7 @@ QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) { if (ToPointeeType.isNull()) return QualType(); - llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols; - for (ObjCObjectPointerType::qual_iterator P = T->qual_begin(), - PEnd = T->qual_end(); - P != PEnd; ++P) { - ObjCProtocolDecl *Protocol - = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(*P)); - if (!Protocol) - return QualType(); - Protocols.push_back(Protocol); - } - - return Importer.getToContext().getObjCObjectPointerType(ToPointeeType, - Protocols.data(), - Protocols.size()); + return Importer.getToContext().getObjCObjectPointerType(ToPointeeType); } //---------------------------------------------------------------------------- @@ -1617,7 +1601,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D2->startDefinition(); ImportDeclContext(D); - D2->completeDefinition(T, ToPromotionType); + + // FIXME: we might need to merge the number of positive or negative bits + // if the enumerator lists don't match. + D2->completeDefinition(T, ToPromotionType, + D->getNumPositiveBits(), + D->getNumNegativeBits()); } return D2; @@ -2961,7 +2950,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { return 0; return ToContext.getTrivialTypeSourceInfo(T, - FromTSI->getTypeLoc().getFullSourceRange().getBegin()); + FromTSI->getTypeLoc().getSourceRange().getBegin()); } Decl *ASTImporter::Import(Decl *FromD) { diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index 423aa065e57c..0fab22caced8 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -74,6 +74,7 @@ void NonNullAttr::Destroy(ASTContext &C) { // FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for // "non-simple" classes? +DEF_SIMPLE_ATTR_CLONE(AlignMac68k) DEF_SIMPLE_ATTR_CLONE(AlwaysInline) DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn) DEF_SIMPLE_ATTR_CLONE(BaseCheck) @@ -100,6 +101,7 @@ DEF_SIMPLE_ATTR_CLONE(Override) DEF_SIMPLE_ATTR_CLONE(Packed) DEF_SIMPLE_ATTR_CLONE(Pure) DEF_SIMPLE_ATTR_CLONE(StdCall) +DEF_SIMPLE_ATTR_CLONE(ThisCall) DEF_SIMPLE_ATTR_CLONE(TransparentUnion) DEF_SIMPLE_ATTR_CLONE(Unavailable) DEF_SIMPLE_ATTR_CLONE(Unused) @@ -110,8 +112,8 @@ DEF_SIMPLE_ATTR_CLONE(WeakImport) DEF_SIMPLE_ATTR_CLONE(WeakRef) DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer) -Attr* PragmaPackAttr::clone(ASTContext &C) const { - return ::new (C) PragmaPackAttr(Alignment); +Attr* MaxFieldAlignmentAttr::clone(ASTContext &C) const { + return ::new (C) MaxFieldAlignmentAttr(Alignment); } Attr* AlignedAttr::clone(ASTContext &C) const { @@ -142,6 +144,10 @@ Attr *IBOutletAttr::clone(ASTContext &C) const { return ::new (C) IBOutletAttr; } +Attr *IBOutletCollectionAttr::clone(ASTContext &C) const { + return ::new (C) IBOutletCollectionAttr(D); +} + Attr *IBActionAttr::clone(ASTContext &C) const { return ::new (C) IBActionAttr; } diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 91aaddc9a481..bce3646feedb 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -39,4 +39,4 @@ add_clang_library(clangAST TypePrinter.cpp ) -add_dependencies(clangAST ClangDiagnosticAST) +add_dependencies(clangAST ClangDiagnosticAST ClangStmtNodes) diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index a9f223045864..d616e42e0076 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -49,9 +49,8 @@ CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() { /// ambiguous, i.e., there are two or more paths that refer to /// different base class subobjects of the same type. BaseType must be /// an unqualified, canonical class type. -bool CXXBasePaths::isAmbiguous(QualType BaseType) { - assert(BaseType.isCanonical() && "Base type must be the canonical type"); - assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified"); +bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { + BaseType = BaseType.getUnqualifiedType(); std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; return Subobjects.second + (Subobjects.first? 1 : 0) > 1; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ffe49671d8a3..ffdcb471d082 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -23,16 +23,11 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Basic/Specifiers.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; -/// \brief Return the TypeLoc wrapper for the type source info. -TypeLoc TypeSourceInfo::getTypeLoc() const { - return TypeLoc(Ty, (void*)(this + 1)); -} - //===----------------------------------------------------------------------===// // NamedDecl Implementation //===----------------------------------------------------------------------===// @@ -541,7 +536,7 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { while (true) { TypeLoc NextTL = TL.getNextTypeLoc(); if (!NextTL) - return TL.getSourceRange().getBegin(); + return TL.getLocalSourceRange().getBegin(); TL = NextTL; } } @@ -1224,9 +1219,8 @@ FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD, } bool FunctionDecl::isImplicitlyInstantiable() const { - // If this function already has a definition or is invalid, it can't be - // implicitly instantiated. - if (isInvalidDecl() || getBody()) + // If the function is invalid, it can't be implicitly instantiated. + if (isInvalidDecl()) return false; switch (getTemplateSpecializationKind()) { @@ -1295,11 +1289,22 @@ FunctionDecl::getTemplateSpecializationArgs() const { return 0; } +const TemplateArgumentListInfo * +FunctionDecl::getTemplateSpecializationArgsAsWritten() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->TemplateArgumentsAsWritten; + } + return 0; +} + void FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, - TemplateSpecializationKind TSK) { + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten) { assert(TSK != TSK_Undeclared && "Must specify the type of function template specialization"); FunctionTemplateSpecializationInfo *Info @@ -1311,6 +1316,7 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, Info->Template.setPointer(Template); Info->Template.setInt(TSK - 1); Info->TemplateArguments = TemplateArgs; + Info->TemplateArgumentsAsWritten = TemplateArgsAsWritten; TemplateOrSpecialization = Info; // Insert this function template specialization into the set of known @@ -1475,6 +1481,12 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } +void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { + TypedefDeclOrQualifier = TDD; + if (TypeForDecl) + TypeForDecl->ClearLinkageCache(); +} + void TagDecl::startDefinition() { if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) { TagT->decl.setPointer(this); @@ -1509,6 +1521,7 @@ void TagDecl::completeDefinition() { TypeForDecl->getAs<InjectedClassNameType>())) { assert(Injected->Decl == this && "Attempt to redefine a class template definition?"); + (void)Injected; } } @@ -1524,16 +1537,6 @@ TagDecl* TagDecl::getDefinition() const { return 0; } -TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) { - switch (TypeSpec) { - default: llvm_unreachable("unexpected type specifier"); - case DeclSpec::TST_struct: return TK_struct; - case DeclSpec::TST_class: return TK_class; - case DeclSpec::TST_union: return TK_union; - case DeclSpec::TST_enum: return TK_enum; - } -} - void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, SourceRange QualifierRange) { if (Qualifier) { @@ -1571,10 +1574,14 @@ void EnumDecl::Destroy(ASTContext& C) { } void EnumDecl::completeDefinition(QualType NewType, - QualType NewPromotionType) { + QualType NewPromotionType, + unsigned NumPositiveBits, + unsigned NumNegativeBits) { assert(!isDefinition() && "Cannot redefine enums!"); IntegerType = NewType; PromotionType = NewPromotionType; + setNumPositiveBits(NumPositiveBits); + setNumNegativeBits(NumNegativeBits); TagDecl::completeDefinition(); } @@ -1620,6 +1627,17 @@ void RecordDecl::completeDefinition() { TagDecl::completeDefinition(); } +ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() { + // Force the decl chain to come into existence properly. + if (!getNextDeclInContext()) getParent()->decls_begin(); + + assert(isAnonymousStructOrUnion()); + ValueDecl *D = cast<ValueDecl>(getNextDeclInContext()); + assert(D->getType()->isRecordType()); + assert(D->getType()->getAs<RecordType>()->getDecl() == this); + return D; +} + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index b5aec0c5125c..42a372632099 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -811,12 +811,12 @@ DeclContext::lookup(DeclarationName Name) { buildLookup(this); if (!LookupPtr) - return lookup_result(0, 0); + return lookup_result(lookup_iterator(0), lookup_iterator(0)); } StoredDeclsMap::iterator Pos = LookupPtr->find(Name); if (Pos == LookupPtr->end()) - return lookup_result(0, 0); + return lookup_result(lookup_iterator(0), lookup_iterator(0)); return Pos->second.getLookupResult(getParentASTContext()); } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 68f4a821e689..cd7afd98b63d 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -137,7 +137,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().VBases[I] = CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, - VBaseClassDecl->getTagKind() == RecordDecl::TK_class, + VBaseClassDecl->getTagKind() == TTK_Class, VBases[I]->getAccessSpecifier(), VBaseType); } } @@ -700,8 +700,9 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), IsVirtual(IsVirtual), - LParenLoc(L), RParenLoc(R) + : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), + LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), + SourceOrderOrNumArrayIndices(0) { } @@ -709,14 +710,46 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) + : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), + AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(0) +{ +} + +CXXBaseOrMemberInitializer:: +CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + SourceLocation L, Expr *Init, SourceLocation R, + VarDecl **Indices, + unsigned NumIndices) : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), - AnonUnionMember(0), LParenLoc(L), RParenLoc(R) + AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { + VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1); + memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *)); +} + +CXXBaseOrMemberInitializer * +CXXBaseOrMemberInitializer::Create(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, + Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices) { + void *Mem = Context.Allocate(sizeof(CXXBaseOrMemberInitializer) + + sizeof(VarDecl *) * NumIndices, + llvm::alignof<CXXBaseOrMemberInitializer>()); + return new (Mem) CXXBaseOrMemberInitializer(Context, Member, MemberLoc, + L, Init, R, Indices, NumIndices); } void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) { if (Init) Init->Destroy(Context); + // FIXME: Destroy indices this->~CXXBaseOrMemberInitializer(); } @@ -745,7 +778,7 @@ SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const { if (isMemberInitializer()) return getMemberLocation(); - return getBaseClassLoc().getSourceRange().getBegin(); + return getBaseClassLoc().getLocalSourceRange().getBegin(); } SourceRange CXXBaseOrMemberInitializer::getSourceRange() const { @@ -753,6 +786,12 @@ SourceRange CXXBaseOrMemberInitializer::getSourceRange() const { } CXXConstructorDecl * +CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationName(), + QualType(), 0, false, false, false); +} + +CXXConstructorDecl * CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -855,6 +894,12 @@ bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { } CXXDestructorDecl * +CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationName(), + QualType(), false, false); +} + +CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, @@ -871,6 +916,12 @@ CXXConstructorDecl::Destroy(ASTContext& C) { } CXXConversionDecl * +CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationName(), + QualType(), 0, false, false); +} + +CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, @@ -908,6 +959,12 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { return cast_or_null<NamespaceDecl>(NominatedNamespace); } +void UsingDirectiveDecl::setNominatedNamespace(NamedDecl* ND) { + assert((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) && + "expected a NamespaceDecl or NamespaceAliasDecl"); + NominatedNamespace = ND; +} + NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation AliasLoc, diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index c498dea17703..26e291c94f64 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -94,6 +94,10 @@ TemplateDecl::~TemplateDecl() { // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// +void FunctionTemplateDecl::DeallocateCommon(void *Ptr) { + static_cast<Common *>(Ptr)->~Common(); +} + FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -129,8 +133,9 @@ FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() { First = First->getPreviousDeclaration(); if (First->CommonOrPrev.isNull()) { - // FIXME: Allocate with the ASTContext - First->CommonOrPrev = new Common; + Common *CommonPtr = new (getASTContext()) Common; + getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); + First->CommonOrPrev = CommonPtr; } return First->CommonOrPrev.get<Common*>(); } @@ -139,6 +144,10 @@ FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() { // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// +void ClassTemplateDecl::DeallocateCommon(void *Ptr) { + static_cast<Common *>(Ptr)->~Common(); +} + ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() { ClassTemplateDecl *Template = this; while (Template->getPreviousDeclaration()) @@ -156,8 +165,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, Common *CommonPtr; if (PrevDecl) CommonPtr = PrevDecl->CommonPtr; - else + else { CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); + } return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl, CommonPtr); @@ -259,7 +270,7 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { - return DefaultArgument->getTypeLoc().getFullSourceRange().getBegin(); + return DefaultArgument->getTypeLoc().getSourceRange().getBegin(); } unsigned TemplateTypeParmDecl::getDepth() const { @@ -303,22 +314,14 @@ TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, // TemplateArgumentListBuilder Implementation //===----------------------------------------------------------------------===// -void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) { - switch (Arg.getKind()) { - default: break; - case TemplateArgument::Type: - assert(Arg.getAsType().isCanonical() && "Type must be canonical!"); - break; - } - - assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!"); +void TemplateArgumentListBuilder::Append(const TemplateArgument &Arg) { + assert((Arg.getKind() != TemplateArgument::Type || + Arg.getAsType().isCanonical()) && "Type must be canonical!"); + assert(FlatArgs.size() < MaxFlatArgs && "Argument list builder is full!"); assert(!StructuredArgs && "Can't append arguments when an argument pack has been added!"); - if (!FlatArgs) - FlatArgs = new TemplateArgument[MaxFlatArgs]; - - FlatArgs[NumFlatArgs++] = Arg; + FlatArgs.push_back(Arg); } void TemplateArgumentListBuilder::BeginPack() { @@ -326,7 +329,7 @@ void TemplateArgumentListBuilder::BeginPack() { assert(!StructuredArgs && "Argument list already contains a pack!"); AddingToPack = true; - PackBeginIndex = NumFlatArgs; + PackBeginIndex = FlatArgs.size(); } void TemplateArgumentListBuilder::EndPack() { @@ -335,6 +338,7 @@ void TemplateArgumentListBuilder::EndPack() { AddingToPack = false; + // FIXME: This is a memory leak! StructuredArgs = new TemplateArgument[MaxStructuredArgs]; // First copy the flat entries over to the list (if any) @@ -346,22 +350,14 @@ void TemplateArgumentListBuilder::EndPack() { // Next, set the pack. TemplateArgument *PackArgs = 0; unsigned NumPackArgs = NumFlatArgs - PackBeginIndex; + // FIXME: NumPackArgs shouldn't be negative here??? if (NumPackArgs) - PackArgs = &FlatArgs[PackBeginIndex]; + PackArgs = FlatArgs.data()+PackBeginIndex; StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs, /*CopyArgs=*/false); } -void TemplateArgumentListBuilder::ReleaseArgs() { - FlatArgs = 0; - NumFlatArgs = 0; - MaxFlatArgs = 0; - StructuredArgs = 0; - NumStructuredArgs = 0; - MaxStructuredArgs = 0; -} - //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// @@ -376,35 +372,56 @@ TemplateArgumentList::TemplateArgumentList(ASTContext &Context, if (!TakeArgs) return; - if (Builder.getStructuredArguments() == Builder.getFlatArguments()) + // If this does take ownership of the arguments, then we have to new them + // and copy over. + TemplateArgument *NewArgs = + new (Context) TemplateArgument[Builder.flatSize()]; + std::copy(Builder.getFlatArguments(), + Builder.getFlatArguments()+Builder.flatSize(), NewArgs); + FlatArguments.setPointer(NewArgs); + + // Just reuse the structured and flat arguments array if possible. + if (Builder.getStructuredArguments() == Builder.getFlatArguments()) { + StructuredArguments.setPointer(NewArgs); StructuredArguments.setInt(0); - Builder.ReleaseArgs(); + } else { + TemplateArgument *NewSArgs = + new (Context) TemplateArgument[Builder.flatSize()]; + std::copy(Builder.getFlatArguments(), + Builder.getFlatArguments()+Builder.flatSize(), NewSArgs); + StructuredArguments.setPointer(NewSArgs); + } } -TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList &Other) - : FlatArguments(Other.FlatArguments.getPointer(), 1), - NumFlatArguments(Other.flat_size()), - StructuredArguments(Other.StructuredArguments.getPointer(), 1), - NumStructuredArguments(Other.NumStructuredArguments) { } +/// Produces a shallow copy of the given template argument list. This +/// assumes that the input argument list outlives it. This takes the list as +/// a pointer to avoid looking like a copy constructor, since this really +/// really isn't safe to use that way. +TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList *Other) + : FlatArguments(Other->FlatArguments.getPointer(), false), + NumFlatArguments(Other->flat_size()), + StructuredArguments(Other->StructuredArguments.getPointer(), false), + NumStructuredArguments(Other->NumStructuredArguments) { } -TemplateArgumentList::~TemplateArgumentList() { - // FIXME: Deallocate template arguments +void TemplateArgumentList::Destroy(ASTContext &C) { + if (FlatArguments.getInt()) + C.Deallocate((void*)FlatArguments.getPointer()); + if (StructuredArguments.getInt()) + C.Deallocate((void*)StructuredArguments.getPointer()); } +TemplateArgumentList::~TemplateArgumentList() {} + //===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// ClassTemplateSpecializationDecl:: -ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, +ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl) - : CXXRecordDecl(DK, - SpecializedTemplate->getTemplatedDecl()->getTagKind(), - DC, L, - // FIXME: Should we use DeclarationName for the name of - // class template specializations? + : CXXRecordDecl(DK, TK, DC, L, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), @@ -414,7 +431,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, } ClassTemplateSpecializationDecl * -ClassTemplateSpecializationDecl::Create(ASTContext &Context, +ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -422,7 +439,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, ClassTemplateSpecializationDecl *Result = new (Context)ClassTemplateSpecializationDecl(Context, ClassTemplateSpecialization, - DC, L, + TK, DC, L, SpecializedTemplate, Builder, PrevDecl); @@ -464,7 +481,7 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { //===----------------------------------------------------------------------===// ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl:: -Create(ASTContext &Context, DeclContext *DC, SourceLocation L, +Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, @@ -478,7 +495,7 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, ClonedArgs[I] = ArgInfos[I]; ClassTemplatePartialSpecializationDecl *Result - = new (Context)ClassTemplatePartialSpecializationDecl(Context, + = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC, L, Params, SpecializedTemplate, Builder, diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 4f85fca53868..343d403e76ad 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -11,10 +11,11 @@ // classes. // //===----------------------------------------------------------------------===// +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" -#include "clang/AST/Decl.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -383,12 +384,12 @@ void DeclarationName::dump() const { llvm::errs() << '\n'; } -DeclarationNameTable::DeclarationNameTable() { +DeclarationNameTable::DeclarationNameTable(ASTContext &C) : Ctx(C) { CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>; // Initialize the overloaded operator names. - CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; + CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { CXXOperatorNames[Op].ExtraKindOrNumArgs = Op + DeclarationNameExtra::CXXConversionFunction; @@ -399,29 +400,32 @@ DeclarationNameTable::DeclarationNameTable() { DeclarationNameTable::~DeclarationNameTable() { llvm::FoldingSet<CXXSpecialName> *SpecialNames = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); - llvm::FoldingSetIterator<CXXSpecialName> - SI = SpecialNames->begin(), SE = SpecialNames->end(); + llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames + = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> + (CXXLiteralOperatorNames); - while (SI != SE) { - CXXSpecialName *n = &*SI++; - delete n; - } + if (Ctx.FreeMemory) { + llvm::FoldingSetIterator<CXXSpecialName> + SI = SpecialNames->begin(), SE = SpecialNames->end(); + while (SI != SE) { + CXXSpecialName *n = &*SI++; + Ctx.Deallocate(n); + } - llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames - = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*> - (CXXLiteralOperatorNames); - llvm::FoldingSetIterator<CXXLiteralOperatorIdName> - LI = LiteralNames->begin(), LE = LiteralNames->end(); + llvm::FoldingSetIterator<CXXLiteralOperatorIdName> + LI = LiteralNames->begin(), LE = LiteralNames->end(); + + while (LI != LE) { + CXXLiteralOperatorIdName *n = &*LI++; + Ctx.Deallocate(n); + } - while (LI != LE) { - CXXLiteralOperatorIdName *n = &*LI++; - delete n; + Ctx.Deallocate(CXXOperatorNames); } delete SpecialNames; delete LiteralNames; - delete [] CXXOperatorNames; } DeclarationName @@ -459,7 +463,7 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName(Name); - CXXSpecialName *SpecialName = new CXXSpecialName; + CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName; SpecialName->ExtraKindOrNumArgs = EKind; SpecialName->Type = Ty; SpecialName->FETokenInfo = 0; @@ -487,7 +491,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { LiteralNames->FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName (Name); - CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName; + CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; LiteralName->ID = II; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 00662a53afed..c38cec32c3b2 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -27,6 +27,8 @@ #include <algorithm> using namespace clang; +void Expr::ANCHOR() {} // key function for Expr class. + /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in @@ -161,8 +163,19 @@ void DeclRefExpr::computeDependence() { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) ValueDependent = true; - } - } + } + // (VD) - FIXME: Missing from the standard: + // - a member function or a static data member of the current + // instantiation + else if (Var->isStaticDataMember() && + Var->getDeclContext()->isDependentContext()) + ValueDependent = true; + } + // (VD) - FIXME: Missing from the standard: + // - a member function or a static data member of the current + // instantiation + else if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) + ValueDependent = true; // (TD) - a nested-name-specifier or a qualified-id that names a // member of an unknown specialization. // (handled by DependentScopeDeclRefExpr) @@ -976,6 +989,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return true; } case CompoundAssignOperatorClass: + case VAArgExprClass: return false; case ConditionalOperatorClass: { @@ -1557,6 +1571,18 @@ Expr *Expr::IgnoreParenCasts() { } } +Expr *Expr::IgnoreParenImpCasts() { + Expr *E = this; + while (true) { + if (ParenExpr *P = dyn_cast<ParenExpr>(E)) + E = P->getSubExpr(); + else if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) + E = P->getSubExpr(); + else + return E; + } +} + /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. @@ -1757,385 +1783,6 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const { return isEvaluatable(Ctx); } -/// isIntegerConstantExpr - this recursive routine will test if an expression is -/// an integer constant expression. - -/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, -/// comma, etc -/// -/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof -/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer -/// cast+dereference. - -// CheckICE - This function does the fundamental ICE checking: the returned -// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation. -// Note that to reduce code duplication, this helper does no evaluation -// itself; the caller checks whether the expression is evaluatable, and -// in the rare cases where CheckICE actually cares about the evaluated -// value, it calls into Evalute. -// -// Meanings of Val: -// 0: This expression is an ICE if it can be evaluated by Evaluate. -// 1: This expression is not an ICE, but if it isn't evaluated, it's -// a legal subexpression for an ICE. This return value is used to handle -// the comma operator in C99 mode. -// 2: This expression is not an ICE, and is not a legal subexpression for one. - -struct ICEDiag { - unsigned Val; - SourceLocation Loc; - - public: - ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {} - ICEDiag() : Val(0) {} -}; - -ICEDiag NoDiag() { return ICEDiag(); } - -static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { - Expr::EvalResult EVResult; - if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || - !EVResult.Val.isInt()) { - return ICEDiag(2, E->getLocStart()); - } - return NoDiag(); -} - -static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { - assert(!E->isValueDependent() && "Should not see value dependent exprs!"); - if (!E->getType()->isIntegralType()) { - return ICEDiag(2, E->getLocStart()); - } - - switch (E->getStmtClass()) { -#define STMT(Node, Base) case Expr::Node##Class: -#define EXPR(Node, Base) -#include "clang/AST/StmtNodes.def" - case Expr::PredefinedExprClass: - case Expr::FloatingLiteralClass: - case Expr::ImaginaryLiteralClass: - case Expr::StringLiteralClass: - case Expr::ArraySubscriptExprClass: - case Expr::MemberExprClass: - case Expr::CompoundAssignOperatorClass: - case Expr::CompoundLiteralExprClass: - case Expr::ExtVectorElementExprClass: - case Expr::InitListExprClass: - case Expr::DesignatedInitExprClass: - case Expr::ImplicitValueInitExprClass: - case Expr::ParenListExprClass: - case Expr::VAArgExprClass: - case Expr::AddrLabelExprClass: - case Expr::StmtExprClass: - case Expr::CXXMemberCallExprClass: - case Expr::CXXDynamicCastExprClass: - case Expr::CXXTypeidExprClass: - case Expr::CXXNullPtrLiteralExprClass: - case Expr::CXXThisExprClass: - case Expr::CXXThrowExprClass: - case Expr::CXXNewExprClass: - case Expr::CXXDeleteExprClass: - case Expr::CXXPseudoDestructorExprClass: - case Expr::UnresolvedLookupExprClass: - case Expr::DependentScopeDeclRefExprClass: - case Expr::CXXConstructExprClass: - case Expr::CXXBindTemporaryExprClass: - case Expr::CXXBindReferenceExprClass: - case Expr::CXXExprWithTemporariesClass: - case Expr::CXXTemporaryObjectExprClass: - case Expr::CXXUnresolvedConstructExprClass: - case Expr::CXXDependentScopeMemberExprClass: - case Expr::UnresolvedMemberExprClass: - case Expr::ObjCStringLiteralClass: - case Expr::ObjCEncodeExprClass: - case Expr::ObjCMessageExprClass: - case Expr::ObjCSelectorExprClass: - case Expr::ObjCProtocolExprClass: - case Expr::ObjCIvarRefExprClass: - case Expr::ObjCPropertyRefExprClass: - case Expr::ObjCImplicitSetterGetterRefExprClass: - case Expr::ObjCSuperExprClass: - case Expr::ObjCIsaExprClass: - case Expr::ShuffleVectorExprClass: - case Expr::BlockExprClass: - case Expr::BlockDeclRefExprClass: - case Expr::NoStmtClass: - return ICEDiag(2, E->getLocStart()); - - case Expr::GNUNullExprClass: - // GCC considers the GNU __null value to be an integral constant expression. - return NoDiag(); - - case Expr::ParenExprClass: - return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx); - case Expr::IntegerLiteralClass: - case Expr::CharacterLiteralClass: - case Expr::CXXBoolLiteralExprClass: - case Expr::CXXZeroInitValueExprClass: - case Expr::TypesCompatibleExprClass: - case Expr::UnaryTypeTraitExprClass: - return NoDiag(); - case Expr::CallExprClass: - case Expr::CXXOperatorCallExprClass: { - const CallExpr *CE = cast<CallExpr>(E); - if (CE->isBuiltinCall(Ctx)) - return CheckEvalInICE(E, Ctx); - return ICEDiag(2, E->getLocStart()); - } - case Expr::DeclRefExprClass: - if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) - return NoDiag(); - if (Ctx.getLangOptions().CPlusPlus && - E->getType().getCVRQualifiers() == Qualifiers::Const) { - const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl(); - - // Parameter variables are never constants. Without this check, - // getAnyInitializer() can find a default argument, which leads - // to chaos. - if (isa<ParmVarDecl>(D)) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - - // C++ 7.1.5.1p2 - // A variable of non-volatile const-qualified integral or enumeration - // type initialized by an ICE can be used in ICEs. - if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { - Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers(); - if (Quals.hasVolatile() || !Quals.hasConst()) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - - // Look for a declaration of this variable that has an initializer. - const VarDecl *ID = 0; - const Expr *Init = Dcl->getAnyInitializer(ID); - if (Init) { - if (ID->isInitKnownICE()) { - // We have already checked whether this subexpression is an - // integral constant expression. - if (ID->isInitICE()) - return NoDiag(); - else - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - } - - // It's an ICE whether or not the definition we found is - // out-of-line. See DR 721 and the discussion in Clang PR - // 6206 for details. - - if (Dcl->isCheckingICE()) { - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - } - - Dcl->setCheckingICE(); - ICEDiag Result = CheckICE(Init, Ctx); - // Cache the result of the ICE test. - Dcl->setInitKnownICE(Result.Val == 0); - return Result; - } - } - } - return ICEDiag(2, E->getLocStart()); - case Expr::UnaryOperatorClass: { - const UnaryOperator *Exp = cast<UnaryOperator>(E); - switch (Exp->getOpcode()) { - case UnaryOperator::PostInc: - case UnaryOperator::PostDec: - case UnaryOperator::PreInc: - case UnaryOperator::PreDec: - case UnaryOperator::AddrOf: - case UnaryOperator::Deref: - return ICEDiag(2, E->getLocStart()); - case UnaryOperator::Extension: - case UnaryOperator::LNot: - case UnaryOperator::Plus: - case UnaryOperator::Minus: - case UnaryOperator::Not: - case UnaryOperator::Real: - case UnaryOperator::Imag: - return CheckICE(Exp->getSubExpr(), Ctx); - case UnaryOperator::OffsetOf: - break; - } - - // OffsetOf falls through here. - } - case Expr::OffsetOfExprClass: { - // Note that per C99, offsetof must be an ICE. And AFAIK, using - // Evaluate matches the proposed gcc behavior for cases like - // "offsetof(struct s{int x[4];}, x[!.0])". This doesn't affect - // compliance: we should warn earlier for offsetof expressions with - // array subscripts that aren't ICEs, and if the array subscripts - // are ICEs, the value of the offsetof must be an integer constant. - return CheckEvalInICE(E, Ctx); - } - case Expr::SizeOfAlignOfExprClass: { - const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E); - if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType()) - return ICEDiag(2, E->getLocStart()); - return NoDiag(); - } - case Expr::BinaryOperatorClass: { - const BinaryOperator *Exp = cast<BinaryOperator>(E); - switch (Exp->getOpcode()) { - case BinaryOperator::PtrMemD: - case BinaryOperator::PtrMemI: - case BinaryOperator::Assign: - case BinaryOperator::MulAssign: - case BinaryOperator::DivAssign: - case BinaryOperator::RemAssign: - case BinaryOperator::AddAssign: - case BinaryOperator::SubAssign: - case BinaryOperator::ShlAssign: - case BinaryOperator::ShrAssign: - case BinaryOperator::AndAssign: - case BinaryOperator::XorAssign: - case BinaryOperator::OrAssign: - return ICEDiag(2, E->getLocStart()); - - case BinaryOperator::Mul: - case BinaryOperator::Div: - case BinaryOperator::Rem: - case BinaryOperator::Add: - case BinaryOperator::Sub: - case BinaryOperator::Shl: - case BinaryOperator::Shr: - case BinaryOperator::LT: - case BinaryOperator::GT: - case BinaryOperator::LE: - case BinaryOperator::GE: - case BinaryOperator::EQ: - case BinaryOperator::NE: - case BinaryOperator::And: - case BinaryOperator::Xor: - case BinaryOperator::Or: - case BinaryOperator::Comma: { - ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); - ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); - if (Exp->getOpcode() == BinaryOperator::Div || - Exp->getOpcode() == BinaryOperator::Rem) { - // Evaluate gives an error for undefined Div/Rem, so make sure - // we don't evaluate one. - if (LHSResult.Val != 2 && RHSResult.Val != 2) { - llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); - if (REval == 0) - return ICEDiag(1, E->getLocStart()); - if (REval.isSigned() && REval.isAllOnesValue()) { - llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx); - if (LEval.isMinSignedValue()) - return ICEDiag(1, E->getLocStart()); - } - } - } - if (Exp->getOpcode() == BinaryOperator::Comma) { - if (Ctx.getLangOptions().C99) { - // C99 6.6p3 introduces a strange edge case: comma can be in an ICE - // if it isn't evaluated. - if (LHSResult.Val == 0 && RHSResult.Val == 0) - return ICEDiag(1, E->getLocStart()); - } else { - // In both C89 and C++, commas in ICEs are illegal. - return ICEDiag(2, E->getLocStart()); - } - } - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; - } - case BinaryOperator::LAnd: - case BinaryOperator::LOr: { - ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); - ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); - if (LHSResult.Val == 0 && RHSResult.Val == 1) { - // Rare case where the RHS has a comma "side-effect"; we need - // to actually check the condition to see whether the side - // with the comma is evaluated. - if ((Exp->getOpcode() == BinaryOperator::LAnd) != - (Exp->getLHS()->EvaluateAsInt(Ctx) == 0)) - return RHSResult; - return NoDiag(); - } - - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; - } - } - } - case Expr::ImplicitCastExprClass: - case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: - case Expr::CXXStaticCastExprClass: - case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: { - const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); - if (SubExpr->getType()->isIntegralType()) - return CheckICE(SubExpr, Ctx); - if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) - return NoDiag(); - return ICEDiag(2, E->getLocStart()); - } - case Expr::ConditionalOperatorClass: { - const ConditionalOperator *Exp = cast<ConditionalOperator>(E); - // If the condition (ignoring parens) is a __builtin_constant_p call, - // then only the true side is actually considered in an integer constant - // expression, and it is fully evaluated. This is an important GNU - // extension. See GCC PR38377 for discussion. - if (const CallExpr *CallCE - = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) { - Expr::EvalResult EVResult; - if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || - !EVResult.Val.isInt()) { - return ICEDiag(2, E->getLocStart()); - } - return NoDiag(); - } - ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); - ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); - ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); - if (CondResult.Val == 2) - return CondResult; - if (TrueResult.Val == 2) - return TrueResult; - if (FalseResult.Val == 2) - return FalseResult; - if (CondResult.Val == 1) - return CondResult; - if (TrueResult.Val == 0 && FalseResult.Val == 0) - return NoDiag(); - // Rare case where the diagnostics depend on which side is evaluated - // Note that if we get here, CondResult is 0, and at least one of - // TrueResult and FalseResult is non-zero. - if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) { - return FalseResult; - } - return TrueResult; - } - case Expr::CXXDefaultArgExprClass: - return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx); - case Expr::ChooseExprClass: { - return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx); - } - } - - // Silence a GCC warning - return ICEDiag(2, E->getLocStart()); -} - -bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, - SourceLocation *Loc, bool isEvaluated) const { - ICEDiag d = CheckICE(this, Ctx); - if (d.Val != 0) { - if (Loc) *Loc = d.Loc; - return false; - } - EvalResult EvalResult; - if (!Evaluate(EvalResult, Ctx)) - 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(); - return true; -} - /// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an /// integer constant expression with the value zero, or if this is one that is /// cast to void*. @@ -2433,9 +2080,9 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { break; case Class: - if (const ObjCInterfaceType *Iface - = getClassReceiver()->getAs<ObjCInterfaceType>()) - return Iface->getDecl(); + if (const ObjCObjectType *Ty + = getClassReceiver()->getAs<ObjCObjectType>()) + return Ty->getInterface(); break; case SuperInstance: @@ -2712,7 +2359,9 @@ Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; } // ObjCImplicitSetterGetterRefExpr Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_begin() { - return &Base; + // If this is accessing a class member, skip that entry. + if (Base) return &Base; + return &Base+1; } Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_end() { return &Base+1; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 2e03beb0f050..d1a2b261f26b 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -92,12 +92,11 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SourceLocation startLoc, SourceLocation endLoc) : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), GlobalNew(globalNew), ParenTypeId(parenTypeId), - Initializer(initializer), Array(arraySize), NumPlacementArgs(numPlaceArgs), - NumConstructorArgs(numConsArgs), OperatorNew(operatorNew), + Initializer(initializer), SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), StartLoc(startLoc), EndLoc(endLoc) { - unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; - SubExprs = new (C) Stmt*[TotalSize]; + + AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); unsigned i = 0; if (Array) SubExprs[i++] = arraySize; @@ -105,9 +104,20 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = placementArgs[j]; for (unsigned j = 0; j < NumConstructorArgs; ++j) SubExprs[i++] = constructorArgs[j]; - assert(i == TotalSize); } +void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, + unsigned numPlaceArgs, unsigned numConsArgs){ + assert(SubExprs == 0 && "SubExprs already allocated"); + Array = isArray; + NumPlacementArgs = numPlaceArgs; + NumConstructorArgs = numConsArgs; + + unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; + SubExprs = new (C) Stmt*[TotalSize]; +} + + void CXXNewExpr::DoDestroy(ASTContext &C) { DestroyChildren(C); if (SubExprs) @@ -134,7 +144,7 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) : Type(Info) { - Location = Info->getTypeLoc().getSourceRange().getBegin(); + Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); } QualType CXXPseudoDestructorExpr::getDestroyedType() const { @@ -147,7 +157,7 @@ QualType CXXPseudoDestructorExpr::getDestroyedType() const { SourceRange CXXPseudoDestructorExpr::getSourceRange() const { SourceLocation End = DestroyedType.getLocation(); if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) - End = TInfo->getTypeLoc().getSourceRange().getEnd(); + End = TInfo->getTypeLoc().getLocalSourceRange().getEnd(); return SourceRange(Base->getLocStart(), End); } @@ -159,23 +169,47 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, DeclarationName Name, SourceLocation NameLoc, bool ADL, - const TemplateArgumentListInfo &Args) + const TemplateArgumentListInfo &Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + ExplicitTemplateArgumentList::sizeFor(Args)); UnresolvedLookupExpr *ULE - = new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + = new (Mem) UnresolvedLookupExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, Dependent, NamingClass, Qualifier, QualifierRange, Name, NameLoc, ADL, /*Overload*/ true, - /*ExplicitTemplateArgs*/ true); + /*ExplicitTemplateArgs*/ true, + Begin, End); reinterpret_cast<ExplicitTemplateArgumentList*>(ULE+1)->initializeFrom(Args); return ULE; } +OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T, + bool Dependent, NestedNameSpecifier *Qualifier, + SourceRange QRange, DeclarationName Name, + SourceLocation NameLoc, bool HasTemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) + : Expr(K, T, Dependent, Dependent), + Results(0), NumResults(End - Begin), Name(Name), Qualifier(Qualifier), + QualifierRange(QRange), NameLoc(NameLoc), + HasExplicitTemplateArgs(HasTemplateArgs) +{ + if (NumResults) { + Results = static_cast<DeclAccessPair *>( + C.Allocate(sizeof(DeclAccessPair) * NumResults, + llvm::alignof<DeclAccessPair>())); + memcpy(Results, &*Begin.getIterator(), + (End - Begin) * sizeof(DeclAccessPair)); + } +} + bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin, UnresolvedSetIterator End, const TemplateArgumentListInfo *Args) { @@ -517,35 +551,43 @@ void CXXConstructExpr::DoDestroy(ASTContext &C) { C.Deallocate(this); } -CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr, +CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C, + Expr *subexpr, CXXTemporary **temps, unsigned numtemps) -: Expr(CXXExprWithTemporariesClass, subexpr->getType(), + : Expr(CXXExprWithTemporariesClass, subexpr->getType(), subexpr->isTypeDependent(), subexpr->isValueDependent()), - SubExpr(subexpr), Temps(0), NumTemps(numtemps) { - if (NumTemps > 0) { - Temps = new CXXTemporary*[NumTemps]; - for (unsigned i = 0; i < NumTemps; ++i) + SubExpr(subexpr), Temps(0), NumTemps(0) { + if (numtemps) { + setNumTemporaries(C, numtemps); + for (unsigned i = 0; i != numtemps; ++i) Temps[i] = temps[i]; } } +void CXXExprWithTemporaries::setNumTemporaries(ASTContext &C, unsigned N) { + assert(Temps == 0 && "Cannot resize with this"); + NumTemps = N; + Temps = new (C) CXXTemporary*[NumTemps]; +} + + CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, unsigned NumTemps) { - return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps); + return new (C) CXXExprWithTemporaries(C, SubExpr, Temps, NumTemps); } void CXXExprWithTemporaries::DoDestroy(ASTContext &C) { DestroyChildren(C); + if (Temps) + C.Deallocate(Temps); this->~CXXExprWithTemporaries(); C.Deallocate(this); } -CXXExprWithTemporaries::~CXXExprWithTemporaries() { - delete[] Temps; -} +CXXExprWithTemporaries::~CXXExprWithTemporaries() {} // CXXBindTemporaryExpr Stmt::child_iterator CXXBindTemporaryExpr::child_begin() { @@ -682,7 +724,8 @@ Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() { return child_iterator(&Base + 1); } -UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, +UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T, + bool Dependent, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, @@ -691,10 +734,12 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, SourceRange QualifierRange, DeclarationName MemberName, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs) - : OverloadExpr(UnresolvedMemberExprClass, T, Dependent, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) + : OverloadExpr(UnresolvedMemberExprClass, C, T, Dependent, Qualifier, QualifierRange, MemberName, MemberLoc, - TemplateArgs != 0), + TemplateArgs != 0, Begin, End), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { if (TemplateArgs) @@ -710,17 +755,19 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, SourceRange QualifierRange, DeclarationName Member, SourceLocation MemberLoc, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { std::size_t size = sizeof(UnresolvedMemberExpr); if (TemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>()); - return new (Mem) UnresolvedMemberExpr( + return new (Mem) UnresolvedMemberExpr(C, Dependent ? C.DependentTy : C.OverloadTy, Dependent, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, Qualifier, QualifierRange, - Member, MemberLoc, TemplateArgs); + Member, MemberLoc, TemplateArgs, Begin, End); } CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c1a42d88fffa..dc614018ec2b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -48,31 +48,110 @@ struct EvalInfo { /// EvalResult - Contains information about the evaluation. Expr::EvalResult &EvalResult; - /// AnyLValue - Stack based LValue results are not discarded. - bool AnyLValue; - - EvalInfo(ASTContext &ctx, Expr::EvalResult& evalresult, - bool anylvalue = false) - : Ctx(ctx), EvalResult(evalresult), AnyLValue(anylvalue) {} + EvalInfo(ASTContext &ctx, Expr::EvalResult& evalresult) + : Ctx(ctx), EvalResult(evalresult) {} }; +namespace { + struct ComplexValue { + private: + bool IsInt; -static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info); -static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info); + public: + APSInt IntReal, IntImag; + APFloat FloatReal, FloatImag; + + ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {} + + void makeComplexFloat() { IsInt = false; } + bool isComplexFloat() const { return !IsInt; } + APFloat &getComplexFloatReal() { return FloatReal; } + APFloat &getComplexFloatImag() { return FloatImag; } + + void makeComplexInt() { IsInt = true; } + bool isComplexInt() const { return IsInt; } + APSInt &getComplexIntReal() { return IntReal; } + APSInt &getComplexIntImag() { return IntImag; } + + void moveInto(APValue &v) { + if (isComplexFloat()) + v = APValue(FloatReal, FloatImag); + else + v = APValue(IntReal, IntImag); + } + }; + + struct LValue { + Expr *Base; + CharUnits Offset; + + Expr *getLValueBase() { return Base; } + CharUnits getLValueOffset() { return Offset; } + + void moveInto(APValue &v) { + v = APValue(Base, Offset); + } + }; +} + +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); +static bool EvaluatePointer(const Expr *E, LValue &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 EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); -static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info); +static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); //===----------------------------------------------------------------------===// // Misc utilities //===----------------------------------------------------------------------===// -static bool EvalPointerValueAsBool(APValue& Value, bool& Result) { - // FIXME: Is this accurate for all kinds of bases? If not, what would - // the check look like? - Result = Value.getLValueBase() || !Value.getLValueOffset().isZero(); +static bool IsGlobalLValue(const Expr* E) { + if (!E) return true; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (isa<FunctionDecl>(DRE->getDecl())) + return true; + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) + return VD->hasGlobalStorage(); + return false; + } + + if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(E)) + return CLE->isFileScope(); + + return true; +} + +static bool EvalPointerValueAsBool(LValue& Value, bool& Result) { + const Expr* Base = Value.Base; + + // A null base expression indicates a null pointer. These are always + // evaluatable, and they are false unless the offset is zero. + if (!Base) { + Result = !Value.Offset.isZero(); + return true; + } + + // Require the base expression to be a global l-value. + if (!IsGlobalLValue(Base)) return false; + + // We have a non-null base expression. These are generally known to + // be true, but if it'a decl-ref to a weak symbol it can be null at + // runtime. + Result = true; + + const DeclRefExpr* DeclRef = dyn_cast<DeclRefExpr>(Base); + if (!DeclRef) + return true; + + // If it's a weak symbol, it isn't constant-evaluable. + const ValueDecl* Decl = DeclRef->getDecl(); + if (Decl->hasAttr<WeakAttr>() || + Decl->hasAttr<WeakRefAttr>() || + Decl->hasAttr<WeakImportAttr>()) + return false; + return true; } @@ -91,12 +170,12 @@ static bool HandleConversionToBool(const Expr* E, bool& Result, Result = !FloatResult.isZero(); return true; } else if (E->getType()->hasPointerRepresentation()) { - APValue PointerResult; + LValue PointerResult; if (!EvaluatePointer(E, PointerResult, Info)) return false; return EvalPointerValueAsBool(PointerResult, Result); } else if (E->getType()->isAnyComplexType()) { - APValue ComplexResult; + ComplexValue ComplexResult; if (!EvaluateComplex(E, ComplexResult, Info)) return false; if (ComplexResult.isComplexFloat()) { @@ -221,34 +300,42 @@ public: //===----------------------------------------------------------------------===// namespace { class LValueExprEvaluator - : public StmtVisitor<LValueExprEvaluator, APValue> { + : public StmtVisitor<LValueExprEvaluator, bool> { EvalInfo &Info; + LValue &Result; + + bool Success(Expr *E) { + Result.Base = E; + Result.Offset = CharUnits::Zero(); + return true; + } public: - LValueExprEvaluator(EvalInfo &info) : Info(info) {} + LValueExprEvaluator(EvalInfo &info, LValue &Result) : + Info(info), Result(Result) {} - APValue VisitStmt(Stmt *S) { - return APValue(); + bool VisitStmt(Stmt *S) { + return false; } - APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - APValue VisitDeclRefExpr(DeclRefExpr *E); - APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); } - APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - APValue VisitMemberExpr(MemberExpr *E); - APValue VisitStringLiteral(StringLiteral *E) { return APValue(E); } - APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E); } - APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E); - APValue VisitUnaryDeref(UnaryOperator *E); - APValue VisitUnaryExtension(const UnaryOperator *E) + bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitDeclRefExpr(DeclRefExpr *E); + bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); } + bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E); + bool VisitMemberExpr(MemberExpr *E); + bool VisitStringLiteral(StringLiteral *E) { return Success(E); } + bool VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return Success(E); } + bool VisitArraySubscriptExpr(ArraySubscriptExpr *E); + bool VisitUnaryDeref(UnaryOperator *E); + bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - APValue VisitChooseExpr(const ChooseExpr *E) + bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } - APValue VisitCastExpr(CastExpr *E) { + bool VisitCastExpr(CastExpr *E) { switch (E->getCastKind()) { default: - return APValue(); + return false; case CastExpr::CK_NoOp: return Visit(E->getSubExpr()); @@ -258,44 +345,41 @@ public: }; } // end anonymous namespace -static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) { - Result = LValueExprEvaluator(Info).Visit(const_cast<Expr*>(E)); - return Result.isLValue(); +static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) { + return LValueExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } -APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) { +bool LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) { if (isa<FunctionDecl>(E->getDecl())) { - return APValue(E); + return Success(E); } else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) { - if (!Info.AnyLValue && !VD->hasGlobalStorage()) - return APValue(); if (!VD->getType()->isReferenceType()) - return APValue(E); + return Success(E); + // Reference parameters can refer to anything even if they have an + // "initializer" in the form of a default argument. + if (isa<ParmVarDecl>(VD)) + return false; // FIXME: Check whether VD might be overridden! if (const Expr *Init = VD->getAnyInitializer()) return Visit(const_cast<Expr *>(Init)); } - return APValue(); + return false; } -APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - if (!Info.AnyLValue && !E->isFileScope()) - return APValue(); - return APValue(E); +bool LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + return Success(E); } -APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { - APValue result; +bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { QualType Ty; if (E->isArrow()) { - if (!EvaluatePointer(E->getBase(), result, Info)) - return APValue(); + if (!EvaluatePointer(E->getBase(), Result, Info)) + return false; Ty = E->getBase()->getType()->getAs<PointerType>()->getPointeeType(); } else { - result = Visit(E->getBase()); - if (result.isUninit()) - return APValue(); + if (!Visit(E->getBase())) + return false; Ty = E->getBase()->getType(); } @@ -304,10 +388,10 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); if (!FD) // FIXME: deal with other kinds of member expressions - return APValue(); + return false; if (FD->getType()->isReferenceType()) - return APValue(); + return false; // FIXME: This is linear time. unsigned i = 0; @@ -318,36 +402,25 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { break; } - result.setLValue(result.getLValueBase(), - result.getLValueOffset() + - CharUnits::fromQuantity(RL.getFieldOffset(i) / 8)); - - return result; + Result.Offset += CharUnits::fromQuantity(RL.getFieldOffset(i) / 8); + return true; } -APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - APValue Result; - +bool LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { if (!EvaluatePointer(E->getBase(), Result, Info)) - return APValue(); + return false; APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) - return APValue(); + return false; CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType()); - - CharUnits Offset = Index.getSExtValue() * ElementSize; - Result.setLValue(Result.getLValueBase(), - Result.getLValueOffset() + Offset); - return Result; + Result.Offset += Index.getSExtValue() * ElementSize; + return true; } -APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { - APValue Result; - if (!EvaluatePointer(E->getSubExpr(), Result, Info)) - return APValue(); - return Result; +bool LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { + return EvaluatePointer(E->getSubExpr(), Result, Info); } //===----------------------------------------------------------------------===// @@ -356,104 +429,103 @@ APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { namespace { class PointerExprEvaluator - : public StmtVisitor<PointerExprEvaluator, APValue> { + : public StmtVisitor<PointerExprEvaluator, bool> { EvalInfo &Info; + LValue &Result; + + bool Success(Expr *E) { + Result.Base = E; + Result.Offset = CharUnits::Zero(); + return true; + } public: - PointerExprEvaluator(EvalInfo &info) : Info(info) {} + PointerExprEvaluator(EvalInfo &info, LValue &Result) + : Info(info), Result(Result) {} - APValue VisitStmt(Stmt *S) { - return APValue(); + bool VisitStmt(Stmt *S) { + return false; } - APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - APValue VisitBinaryOperator(const BinaryOperator *E); - APValue VisitCastExpr(CastExpr* E); - APValue VisitUnaryExtension(const UnaryOperator *E) + bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitCastExpr(CastExpr* E); + bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - APValue VisitUnaryAddrOf(const UnaryOperator *E); - APValue VisitObjCStringLiteral(ObjCStringLiteral *E) - { return APValue(E); } - APValue VisitAddrLabelExpr(AddrLabelExpr *E) - { return APValue(E); } - APValue VisitCallExpr(CallExpr *E); - APValue VisitBlockExpr(BlockExpr *E) { + bool VisitUnaryAddrOf(const UnaryOperator *E); + bool VisitObjCStringLiteral(ObjCStringLiteral *E) + { return Success(E); } + bool VisitAddrLabelExpr(AddrLabelExpr *E) + { return Success(E); } + bool VisitCallExpr(CallExpr *E); + bool VisitBlockExpr(BlockExpr *E) { if (!E->hasBlockDeclRefExprs()) - return APValue(E); - return APValue(); + return Success(E); + return false; } - APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) - { return APValue((Expr*)0); } - APValue VisitConditionalOperator(ConditionalOperator *E); - APValue VisitChooseExpr(ChooseExpr *E) + bool VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) + { return Success((Expr*)0); } + bool VisitConditionalOperator(ConditionalOperator *E); + bool VisitChooseExpr(ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } - APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) - { return APValue((Expr*)0); } + bool VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) + { return Success((Expr*)0); } // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace -static bool EvaluatePointer(const Expr* E, APValue& Result, EvalInfo &Info) { - if (!E->getType()->hasPointerRepresentation()) - return false; - Result = PointerExprEvaluator(Info).Visit(const_cast<Expr*>(E)); - return Result.isLValue(); +static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { + assert(E->getType()->hasPointerRepresentation()); + return PointerExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } -APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { +bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->getOpcode() != BinaryOperator::Add && E->getOpcode() != BinaryOperator::Sub) - return APValue(); + return false; const Expr *PExp = E->getLHS(); const Expr *IExp = E->getRHS(); if (IExp->getType()->isPointerType()) std::swap(PExp, IExp); - APValue ResultLValue; - if (!EvaluatePointer(PExp, ResultLValue, Info)) - return APValue(); + if (!EvaluatePointer(PExp, Result, Info)) + return false; - llvm::APSInt AdditionalOffset; - if (!EvaluateInteger(IExp, AdditionalOffset, Info)) - return APValue(); + llvm::APSInt Offset; + if (!EvaluateInteger(IExp, Offset, Info)) + return false; + int64_t AdditionalOffset + = Offset.isSigned() ? Offset.getSExtValue() + : static_cast<int64_t>(Offset.getZExtValue()); // Compute the new offset in the appropriate width. QualType PointeeType = PExp->getType()->getAs<PointerType>()->getPointeeType(); - llvm::APSInt SizeOfPointee(AdditionalOffset); + CharUnits SizeOfPointee; // Explicitly handle GNU void* and function pointer arithmetic extensions. if (PointeeType->isVoidType() || PointeeType->isFunctionType()) - SizeOfPointee = 1; + SizeOfPointee = CharUnits::One(); else - SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType).getQuantity(); + SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType); - llvm::APSInt Offset(AdditionalOffset); - Offset = ResultLValue.getLValueOffset().getQuantity(); if (E->getOpcode() == BinaryOperator::Add) - Offset += AdditionalOffset * SizeOfPointee; + Result.Offset += AdditionalOffset * SizeOfPointee; else - Offset -= AdditionalOffset * SizeOfPointee; + Result.Offset -= AdditionalOffset * SizeOfPointee; - // Sign extend prior to converting back to a char unit. - if (Offset.getBitWidth() < 64) - Offset.extend(64); - return APValue(ResultLValue.getLValueBase(), - CharUnits::fromQuantity(Offset.getLimitedValue())); + return true; } -APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { - APValue result; - if (EvaluateLValue(E->getSubExpr(), result, Info)) - return result; - return APValue(); +bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { + return EvaluateLValue(E->getSubExpr(), Result, Info); } -APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) { +bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { @@ -471,18 +543,20 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) { return Visit(SubExpr); if (SubExpr->getType()->isIntegralType()) { - APValue Result; - if (!EvaluateIntegerOrLValue(SubExpr, Result, Info)) + APValue Value; + if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; - if (Result.isInt()) { - Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); - return APValue(0, - CharUnits::fromQuantity(Result.getInt().getZExtValue())); + if (Value.isInt()) { + Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); + Result.Base = 0; + Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue()); + return true; + } else { + Result.Base = Value.getLValueBase(); + Result.Offset = Value.getLValueOffset(); + return true; } - - // Cast is of an lvalue, no need to change value. - return Result; } break; } @@ -494,51 +568,46 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) { return Visit(SubExpr); case CastExpr::CK_IntegralToPointer: { - APValue Result; - if (!EvaluateIntegerOrLValue(SubExpr, Result, Info)) + APValue Value; + if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; - if (Result.isInt()) { - Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); - return APValue(0, - CharUnits::fromQuantity(Result.getInt().getZExtValue())); + if (Value.isInt()) { + Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); + Result.Base = 0; + Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue()); + return true; + } else { + // Cast is of an lvalue, no need to change value. + Result.Base = Value.getLValueBase(); + Result.Offset = Value.getLValueOffset(); + return true; } - - // Cast is of an lvalue, no need to change value. - return Result; } case CastExpr::CK_ArrayToPointerDecay: - case CastExpr::CK_FunctionToPointerDecay: { - APValue Result; - if (EvaluateLValue(SubExpr, Result, Info)) - return Result; - break; - } + case CastExpr::CK_FunctionToPointerDecay: + return EvaluateLValue(SubExpr, Result, Info); } - return APValue(); + return false; } -APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) { +bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) { if (E->isBuiltinCall(Info.Ctx) == Builtin::BI__builtin___CFStringMakeConstantString || E->isBuiltinCall(Info.Ctx) == Builtin::BI__builtin___NSStringMakeConstantString) - return APValue(E); - return APValue(); + return Success(E); + return false; } -APValue PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { +bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { bool BoolResult; if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) - return APValue(); + return false; Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); - - APValue Result; - if (EvaluatePointer(EvalExpr, Result, Info)) - return Result; - return APValue(); + return Visit(EvalExpr); } //===----------------------------------------------------------------------===// @@ -867,18 +936,20 @@ public: private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); + static QualType GetObjectType(const Expr *E); + bool TryEvaluateBuiltinObjectSize(CallExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) { - if (!E->getType()->isIntegralType()) - return false; - + assert(E->getType()->isIntegralType()); return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { + assert(E->getType()->isIntegralType()); + APValue Val; if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt()) return false; @@ -984,36 +1055,55 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { return -1; } +/// Retrieves the "underlying object type" of the given expression, +/// as used by __builtin_object_size. +QualType IntExprEvaluator::GetObjectType(const Expr *E) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) + return VD->getType(); + } else if (isa<CompoundLiteralExpr>(E)) { + return E->getType(); + } + + return QualType(); +} + +bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) { + // TODO: Perhaps we should let LLVM lower this? + LValue Base; + if (!EvaluatePointer(E->getArg(0), Base, Info)) + return false; + + // If we can prove the base is null, lower to zero now. + const Expr *LVBase = Base.getLValueBase(); + if (!LVBase) return Success(0, E); + + QualType T = GetObjectType(LVBase); + if (T.isNull() || + T->isIncompleteType() || + !T->isObjectType() || + T->isVariablyModifiedType() || + T->isDependentType()) + return false; + + CharUnits Size = Info.Ctx.getTypeSizeInChars(T); + CharUnits Offset = Base.getLValueOffset(); + + if (!Offset.isNegative() && Offset <= Size) + Size -= Offset; + else + Size = CharUnits::Zero(); + return Success(Size.getQuantity(), E); +} + bool IntExprEvaluator::VisitCallExpr(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; - - // TODO: Perhaps we should let LLVM lower this? - 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()) { - CharUnits Size = Info.Ctx.getTypeSizeInChars(VD->getType()); - CharUnits Offset = Base.Val.getLValueOffset(); - if (!Offset.isNegative() && Offset <= Size) - Size -= Offset; - else - Size = CharUnits::Zero(); - return Success(Size.getQuantity(), E); - } - } - } + if (TryEvaluateBuiltinObjectSize(E)) + return true; // If evaluating the argument has side-effects we can't determine // the size of the object and lower it to unknown now. @@ -1098,7 +1188,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (LHSTy->isAnyComplexType()) { assert(RHSTy->isAnyComplexType() && "Invalid comparison"); - APValue LHS, RHS; + ComplexValue LHS, RHS; if (!EvaluateComplex(E->getLHS(), LHS, Info)) return false; @@ -1173,11 +1263,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (LHSTy->isPointerType() && RHSTy->isPointerType()) { if (E->getOpcode() == BinaryOperator::Sub || E->isEqualityOp()) { - APValue LHSValue; + LValue LHSValue; if (!EvaluatePointer(E->getLHS(), LHSValue, Info)) return false; - APValue RHSValue; + LValue RHSValue; if (!EvaluatePointer(E->getRHS(), RHSValue, Info)) return false; @@ -1463,7 +1553,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (E->isOffsetOfOp()) { // The AST for offsetof is defined in such a way that we can just // directly Evaluate it as an l-value. - APValue LV; + LValue LV; if (!EvaluateLValue(E->getSubExpr(), LV, Info)) return false; if (LV.getLValueBase()) @@ -1538,7 +1628,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { // FIXME: Clean this up! if (SrcType->isPointerType()) { - APValue LV; + LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) return false; @@ -1547,7 +1637,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) return false; - Result = LV; + LV.moveInto(Result); return true; } @@ -1559,19 +1649,19 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { if (SrcType->isArrayType() || SrcType->isFunctionType()) { // This handles double-conversion cases, where there's both // an l-value promotion and an implicit conversion to int. - APValue LV; + LValue LV; if (!EvaluateLValue(SubExpr, LV, Info)) return false; if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(Info.Ctx.VoidPtrTy)) return false; - Result = LV; + LV.moveInto(Result); return true; } if (SrcType->isAnyComplexType()) { - APValue C; + ComplexValue C; if (!EvaluateComplex(SubExpr, C, Info)) return false; if (C.isComplexFloat()) @@ -1596,7 +1686,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { - APValue LV; + ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt()) return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); return Success(LV.getComplexIntReal(), E); @@ -1607,7 +1697,7 @@ bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isComplexIntegerType()) { - APValue LV; + ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt()) return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); return Success(LV.getComplexIntImag(), E); @@ -1649,13 +1739,16 @@ public: { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } + bool VisitUnaryReal(const UnaryOperator *E); + bool VisitUnaryImag(const UnaryOperator *E); - // FIXME: Missing: __real__/__imag__, array subscript of vector, - // member of vector, ImplicitValueInitExpr + // FIXME: Missing: array subscript of vector, member of vector, + // ImplicitValueInitExpr }; } // end anonymous namespace static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { + assert(E->getType()->isRealFloatingType()); return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } @@ -1736,6 +1829,22 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { } } +bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { + ComplexValue CV; + if (!EvaluateComplex(E->getSubExpr(), CV, Info)) + return false; + Result = CV.FloatReal; + return true; +} + +bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { + ComplexValue CV; + if (!EvaluateComplex(E->getSubExpr(), CV, Info)) + return false; + Result = CV.FloatImag; + return true; +} + bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (E->getOpcode() == UnaryOperator::Deref) return false; @@ -1838,166 +1947,170 @@ bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { namespace { class ComplexExprEvaluator - : public StmtVisitor<ComplexExprEvaluator, APValue> { + : public StmtVisitor<ComplexExprEvaluator, bool> { EvalInfo &Info; + ComplexValue &Result; public: - ComplexExprEvaluator(EvalInfo &info) : Info(info) {} + ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result) + : Info(info), Result(Result) {} //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// - APValue VisitStmt(Stmt *S) { - return APValue(); + bool VisitStmt(Stmt *S) { + return false; } - APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - APValue VisitImaginaryLiteral(ImaginaryLiteral *E) { + bool VisitImaginaryLiteral(ImaginaryLiteral *E) { Expr* SubExpr = E->getSubExpr(); if (SubExpr->getType()->isRealFloatingType()) { - APFloat Result(0.0); - - if (!EvaluateFloat(SubExpr, Result, Info)) - return APValue(); + Result.makeComplexFloat(); + APFloat &Imag = Result.FloatImag; + if (!EvaluateFloat(SubExpr, Imag, Info)) + return false; - return APValue(APFloat(Result.getSemantics(), APFloat::fcZero, false), - Result); + Result.FloatReal = APFloat(Imag.getSemantics()); + return true; } else { assert(SubExpr->getType()->isIntegerType() && "Unexpected imaginary literal."); - llvm::APSInt Result; - if (!EvaluateInteger(SubExpr, Result, Info)) - return APValue(); + Result.makeComplexInt(); + APSInt &Imag = Result.IntImag; + if (!EvaluateInteger(SubExpr, Imag, Info)) + return false; - llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned()); - Zero = 0; - return APValue(Zero, Result); + Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned()); + return true; } } - APValue VisitCastExpr(CastExpr *E) { + bool VisitCastExpr(CastExpr *E) { Expr* SubExpr = E->getSubExpr(); QualType EltType = E->getType()->getAs<ComplexType>()->getElementType(); QualType SubType = SubExpr->getType(); if (SubType->isRealFloatingType()) { - APFloat Result(0.0); - - if (!EvaluateFloat(SubExpr, Result, Info)) - return APValue(); + APFloat &Real = Result.FloatReal; + if (!EvaluateFloat(SubExpr, Real, Info)) + return false; if (EltType->isRealFloatingType()) { - Result = HandleFloatToFloatCast(EltType, SubType, Result, Info.Ctx); - return APValue(Result, - APFloat(Result.getSemantics(), APFloat::fcZero, false)); + Result.makeComplexFloat(); + Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx); + Result.FloatImag = APFloat(Real.getSemantics()); + return true; } else { - llvm::APSInt IResult; - IResult = HandleFloatToIntCast(EltType, SubType, Result, Info.Ctx); - llvm::APSInt Zero(IResult.getBitWidth(), !IResult.isSigned()); - Zero = 0; - return APValue(IResult, Zero); + Result.makeComplexInt(); + Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx); + Result.IntImag = APSInt(Result.IntReal.getBitWidth(), + !Result.IntReal.isSigned()); + return true; } } else if (SubType->isIntegerType()) { - APSInt Result; - - if (!EvaluateInteger(SubExpr, Result, Info)) - return APValue(); + APSInt &Real = Result.IntReal; + if (!EvaluateInteger(SubExpr, Real, Info)) + return false; if (EltType->isRealFloatingType()) { - APFloat FResult = - HandleIntToFloatCast(EltType, SubType, Result, Info.Ctx); - return APValue(FResult, - APFloat(FResult.getSemantics(), APFloat::fcZero, false)); + Result.makeComplexFloat(); + Result.FloatReal + = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx); + Result.FloatImag = APFloat(Result.FloatReal.getSemantics()); + return true; } else { - Result = HandleIntToIntCast(EltType, SubType, Result, Info.Ctx); - llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned()); - Zero = 0; - return APValue(Result, Zero); + Result.makeComplexInt(); + Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx); + Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); + return true; } } else if (const ComplexType *CT = SubType->getAs<ComplexType>()) { - APValue Src; - - if (!EvaluateComplex(SubExpr, Src, Info)) - return APValue(); + if (!Visit(SubExpr)) + return false; QualType SrcType = CT->getElementType(); - if (Src.isComplexFloat()) { + if (Result.isComplexFloat()) { if (EltType->isRealFloatingType()) { - return APValue(HandleFloatToFloatCast(EltType, SrcType, - Src.getComplexFloatReal(), - Info.Ctx), - HandleFloatToFloatCast(EltType, SrcType, - Src.getComplexFloatImag(), - Info.Ctx)); + Result.makeComplexFloat(); + Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType, + Result.FloatReal, + Info.Ctx); + Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType, + Result.FloatImag, + Info.Ctx); + return true; } else { - return APValue(HandleFloatToIntCast(EltType, SrcType, - Src.getComplexFloatReal(), - Info.Ctx), - HandleFloatToIntCast(EltType, SrcType, - Src.getComplexFloatImag(), - Info.Ctx)); + Result.makeComplexInt(); + Result.IntReal = HandleFloatToIntCast(EltType, SrcType, + Result.FloatReal, + Info.Ctx); + Result.IntImag = HandleFloatToIntCast(EltType, SrcType, + Result.FloatImag, + Info.Ctx); + return true; } } else { - assert(Src.isComplexInt() && "Invalid evaluate result."); + assert(Result.isComplexInt() && "Invalid evaluate result."); if (EltType->isRealFloatingType()) { - return APValue(HandleIntToFloatCast(EltType, SrcType, - Src.getComplexIntReal(), - Info.Ctx), - HandleIntToFloatCast(EltType, SrcType, - Src.getComplexIntImag(), - Info.Ctx)); + Result.makeComplexFloat(); + Result.FloatReal = HandleIntToFloatCast(EltType, SrcType, + Result.IntReal, + Info.Ctx); + Result.FloatImag = HandleIntToFloatCast(EltType, SrcType, + Result.IntImag, + Info.Ctx); + return true; } else { - return APValue(HandleIntToIntCast(EltType, SrcType, - Src.getComplexIntReal(), - Info.Ctx), - HandleIntToIntCast(EltType, SrcType, - Src.getComplexIntImag(), - Info.Ctx)); + Result.makeComplexInt(); + Result.IntReal = HandleIntToIntCast(EltType, SrcType, + Result.IntReal, + Info.Ctx); + Result.IntImag = HandleIntToIntCast(EltType, SrcType, + Result.IntImag, + Info.Ctx); + return true; } } } // FIXME: Handle more casts. - return APValue(); + return false; } - APValue VisitBinaryOperator(const BinaryOperator *E); - APValue VisitChooseExpr(const ChooseExpr *E) + bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } - APValue VisitUnaryExtension(const UnaryOperator *E) + bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr, // conditional ?:, comma }; } // end anonymous namespace -static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info) { - Result = ComplexExprEvaluator(Info).Visit(const_cast<Expr*>(E)); - assert((!Result.isComplexFloat() || - (&Result.getComplexFloatReal().getSemantics() == - &Result.getComplexFloatImag().getSemantics())) && - "Invalid complex evaluation."); - return Result.isComplexFloat() || Result.isComplexInt(); +static bool EvaluateComplex(const Expr *E, ComplexValue &Result, + EvalInfo &Info) { + assert(E->getType()->isAnyComplexType()); + return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E)); } -APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { - APValue Result, RHS; - - if (!EvaluateComplex(E->getLHS(), Result, Info)) - return APValue(); +bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + if (!Visit(E->getLHS())) + return false; + ComplexValue RHS; if (!EvaluateComplex(E->getRHS(), RHS, Info)) - return APValue(); + return false; assert(Result.isComplexFloat() == RHS.isComplexFloat() && "Invalid operands to binary operator."); switch (E->getOpcode()) { - default: return APValue(); + default: return false; case BinaryOperator::Add: if (Result.isComplexFloat()) { Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), @@ -2022,7 +2135,7 @@ APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { break; case BinaryOperator::Mul: if (Result.isComplexFloat()) { - APValue LHS = Result; + ComplexValue LHS = Result; APFloat &LHS_r = LHS.getComplexFloatReal(); APFloat &LHS_i = LHS.getComplexFloatImag(); APFloat &RHS_r = RHS.getComplexFloatReal(); @@ -2042,7 +2155,7 @@ APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven); Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven); } else { - APValue LHS = Result; + ComplexValue LHS = Result; Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() - LHS.getComplexIntImag() * RHS.getComplexIntImag()); @@ -2053,7 +2166,7 @@ APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { break; } - return Result; + return true; } //===----------------------------------------------------------------------===// @@ -2065,53 +2178,32 @@ APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { /// we want to. If this function returns true, it returns the folded constant /// in Result. bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { + const Expr *E = this; EvalInfo Info(Ctx, Result); - - if (getType()->isVectorType()) { - if (!EvaluateVector(this, Result.Val, Info)) + if (E->getType()->isVectorType()) { + if (!EvaluateVector(E, Info.EvalResult.Val, Info)) return false; - } else if (getType()->isIntegerType()) { - if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this))) + } else if (E->getType()->isIntegerType()) { + if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E))) 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::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))) + } else if (E->getType()->hasPointerRepresentation()) { + LValue LV; + if (!EvaluatePointer(E, LV, Info)) return false; - } else if (getType()->hasPointerRepresentation()) { - if (!EvaluatePointer(this, Result.Val, Info)) + if (!IsGlobalLValue(LV.Base)) return false; - } else if (getType()->isRealFloatingType()) { - llvm::APFloat f(0.0); - if (!EvaluateFloat(this, f, Info)) + LV.moveInto(Info.EvalResult.Val); + } else if (E->getType()->isRealFloatingType()) { + llvm::APFloat F(0.0); + if (!EvaluateFloat(E, F, Info)) return false; - Result.Val = APValue(f); - } else if (getType()->isAnyComplexType()) { - if (!EvaluateComplex(this, Result.Val, Info)) + Info.EvalResult.Val = APValue(F); + } else if (E->getType()->isAnyComplexType()) { + ComplexValue C; + if (!EvaluateComplex(E, C, Info)) return false; + C.moveInto(Info.EvalResult.Val); } else return false; @@ -2128,13 +2220,25 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const { bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); - return EvaluateLValue(this, Result.Val, Info) && !Result.HasSideEffects; + LValue LV; + if (EvaluateLValue(this, LV, Info) && + !Result.HasSideEffects && + IsGlobalLValue(LV.Base)) { + LV.moveInto(Result.Val); + return true; + } + return false; } bool Expr::EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const { - EvalInfo Info(Ctx, Result, true); + EvalInfo Info(Ctx, Result); - return EvaluateLValue(this, Result.Val, Info) && !Result.HasSideEffects; + LValue LV; + if (EvaluateLValue(this, LV, Info)) { + LV.moveInto(Result.Val); + return true; + } + return false; } /// isEvaluatable - Call Evaluate to see if this expression can be constant @@ -2159,3 +2263,388 @@ APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const { return EvalResult.Val.getInt(); } + + bool Expr::EvalResult::isGlobalLValue() const { + assert(Val.isLValue()); + return IsGlobalLValue(Val.getLValueBase()); + } + + +/// isIntegerConstantExpr - this recursive routine will test if an expression is +/// an integer constant expression. + +/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, +/// comma, etc +/// +/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof +/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer +/// cast+dereference. + +// CheckICE - This function does the fundamental ICE checking: the returned +// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation. +// Note that to reduce code duplication, this helper does no evaluation +// itself; the caller checks whether the expression is evaluatable, and +// in the rare cases where CheckICE actually cares about the evaluated +// value, it calls into Evalute. +// +// Meanings of Val: +// 0: This expression is an ICE if it can be evaluated by Evaluate. +// 1: This expression is not an ICE, but if it isn't evaluated, it's +// a legal subexpression for an ICE. This return value is used to handle +// the comma operator in C99 mode. +// 2: This expression is not an ICE, and is not a legal subexpression for one. + +struct ICEDiag { + unsigned Val; + SourceLocation Loc; + + public: + ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {} + ICEDiag() : Val(0) {} +}; + +ICEDiag NoDiag() { return ICEDiag(); } + +static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { + Expr::EvalResult EVResult; + if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || + !EVResult.Val.isInt()) { + return ICEDiag(2, E->getLocStart()); + } + return NoDiag(); +} + +static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { + assert(!E->isValueDependent() && "Should not see value dependent exprs!"); + if (!E->getType()->isIntegralType()) { + return ICEDiag(2, E->getLocStart()); + } + + switch (E->getStmtClass()) { +#define STMT(Node, Base) case Expr::Node##Class: +#define EXPR(Node, Base) +#include "clang/AST/StmtNodes.inc" + case Expr::PredefinedExprClass: + case Expr::FloatingLiteralClass: + case Expr::ImaginaryLiteralClass: + case Expr::StringLiteralClass: + case Expr::ArraySubscriptExprClass: + case Expr::MemberExprClass: + case Expr::CompoundAssignOperatorClass: + case Expr::CompoundLiteralExprClass: + case Expr::ExtVectorElementExprClass: + case Expr::InitListExprClass: + case Expr::DesignatedInitExprClass: + case Expr::ImplicitValueInitExprClass: + case Expr::ParenListExprClass: + case Expr::VAArgExprClass: + case Expr::AddrLabelExprClass: + case Expr::StmtExprClass: + case Expr::CXXMemberCallExprClass: + case Expr::CXXDynamicCastExprClass: + case Expr::CXXTypeidExprClass: + case Expr::CXXNullPtrLiteralExprClass: + case Expr::CXXThisExprClass: + case Expr::CXXThrowExprClass: + case Expr::CXXNewExprClass: + case Expr::CXXDeleteExprClass: + case Expr::CXXPseudoDestructorExprClass: + case Expr::UnresolvedLookupExprClass: + case Expr::DependentScopeDeclRefExprClass: + case Expr::CXXConstructExprClass: + case Expr::CXXBindTemporaryExprClass: + case Expr::CXXBindReferenceExprClass: + case Expr::CXXExprWithTemporariesClass: + case Expr::CXXTemporaryObjectExprClass: + case Expr::CXXUnresolvedConstructExprClass: + case Expr::CXXDependentScopeMemberExprClass: + case Expr::UnresolvedMemberExprClass: + case Expr::ObjCStringLiteralClass: + case Expr::ObjCEncodeExprClass: + case Expr::ObjCMessageExprClass: + case Expr::ObjCSelectorExprClass: + case Expr::ObjCProtocolExprClass: + case Expr::ObjCIvarRefExprClass: + case Expr::ObjCPropertyRefExprClass: + case Expr::ObjCImplicitSetterGetterRefExprClass: + case Expr::ObjCSuperExprClass: + case Expr::ObjCIsaExprClass: + case Expr::ShuffleVectorExprClass: + case Expr::BlockExprClass: + case Expr::BlockDeclRefExprClass: + case Expr::NoStmtClass: + return ICEDiag(2, E->getLocStart()); + + case Expr::GNUNullExprClass: + // GCC considers the GNU __null value to be an integral constant expression. + return NoDiag(); + + case Expr::ParenExprClass: + return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx); + case Expr::IntegerLiteralClass: + case Expr::CharacterLiteralClass: + case Expr::CXXBoolLiteralExprClass: + case Expr::CXXZeroInitValueExprClass: + case Expr::TypesCompatibleExprClass: + case Expr::UnaryTypeTraitExprClass: + return NoDiag(); + case Expr::CallExprClass: + case Expr::CXXOperatorCallExprClass: { + const CallExpr *CE = cast<CallExpr>(E); + if (CE->isBuiltinCall(Ctx)) + return CheckEvalInICE(E, Ctx); + return ICEDiag(2, E->getLocStart()); + } + case Expr::DeclRefExprClass: + if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) + return NoDiag(); + if (Ctx.getLangOptions().CPlusPlus && + E->getType().getCVRQualifiers() == Qualifiers::Const) { + const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl(); + + // Parameter variables are never constants. Without this check, + // getAnyInitializer() can find a default argument, which leads + // to chaos. + if (isa<ParmVarDecl>(D)) + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + + // C++ 7.1.5.1p2 + // A variable of non-volatile const-qualified integral or enumeration + // type initialized by an ICE can be used in ICEs. + if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { + Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers(); + if (Quals.hasVolatile() || !Quals.hasConst()) + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + + // Look for a declaration of this variable that has an initializer. + const VarDecl *ID = 0; + const Expr *Init = Dcl->getAnyInitializer(ID); + if (Init) { + if (ID->isInitKnownICE()) { + // We have already checked whether this subexpression is an + // integral constant expression. + if (ID->isInitICE()) + return NoDiag(); + else + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + } + + // It's an ICE whether or not the definition we found is + // out-of-line. See DR 721 and the discussion in Clang PR + // 6206 for details. + + if (Dcl->isCheckingICE()) { + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + } + + Dcl->setCheckingICE(); + ICEDiag Result = CheckICE(Init, Ctx); + // Cache the result of the ICE test. + Dcl->setInitKnownICE(Result.Val == 0); + return Result; + } + } + } + return ICEDiag(2, E->getLocStart()); + case Expr::UnaryOperatorClass: { + const UnaryOperator *Exp = cast<UnaryOperator>(E); + switch (Exp->getOpcode()) { + case UnaryOperator::PostInc: + case UnaryOperator::PostDec: + case UnaryOperator::PreInc: + case UnaryOperator::PreDec: + case UnaryOperator::AddrOf: + case UnaryOperator::Deref: + return ICEDiag(2, E->getLocStart()); + case UnaryOperator::Extension: + case UnaryOperator::LNot: + case UnaryOperator::Plus: + case UnaryOperator::Minus: + case UnaryOperator::Not: + case UnaryOperator::Real: + case UnaryOperator::Imag: + return CheckICE(Exp->getSubExpr(), Ctx); + case UnaryOperator::OffsetOf: + break; + } + + // OffsetOf falls through here. + } + case Expr::OffsetOfExprClass: { + // Note that per C99, offsetof must be an ICE. And AFAIK, using + // Evaluate matches the proposed gcc behavior for cases like + // "offsetof(struct s{int x[4];}, x[!.0])". This doesn't affect + // compliance: we should warn earlier for offsetof expressions with + // array subscripts that aren't ICEs, and if the array subscripts + // are ICEs, the value of the offsetof must be an integer constant. + return CheckEvalInICE(E, Ctx); + } + case Expr::SizeOfAlignOfExprClass: { + const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E); + if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType()) + return ICEDiag(2, E->getLocStart()); + return NoDiag(); + } + case Expr::BinaryOperatorClass: { + const BinaryOperator *Exp = cast<BinaryOperator>(E); + switch (Exp->getOpcode()) { + case BinaryOperator::PtrMemD: + case BinaryOperator::PtrMemI: + case BinaryOperator::Assign: + case BinaryOperator::MulAssign: + case BinaryOperator::DivAssign: + case BinaryOperator::RemAssign: + case BinaryOperator::AddAssign: + case BinaryOperator::SubAssign: + case BinaryOperator::ShlAssign: + case BinaryOperator::ShrAssign: + case BinaryOperator::AndAssign: + case BinaryOperator::XorAssign: + case BinaryOperator::OrAssign: + return ICEDiag(2, E->getLocStart()); + + case BinaryOperator::Mul: + case BinaryOperator::Div: + case BinaryOperator::Rem: + case BinaryOperator::Add: + case BinaryOperator::Sub: + case BinaryOperator::Shl: + case BinaryOperator::Shr: + case BinaryOperator::LT: + case BinaryOperator::GT: + case BinaryOperator::LE: + case BinaryOperator::GE: + case BinaryOperator::EQ: + case BinaryOperator::NE: + case BinaryOperator::And: + case BinaryOperator::Xor: + case BinaryOperator::Or: + case BinaryOperator::Comma: { + ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); + ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); + if (Exp->getOpcode() == BinaryOperator::Div || + Exp->getOpcode() == BinaryOperator::Rem) { + // Evaluate gives an error for undefined Div/Rem, so make sure + // we don't evaluate one. + if (LHSResult.Val != 2 && RHSResult.Val != 2) { + llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); + if (REval == 0) + return ICEDiag(1, E->getLocStart()); + if (REval.isSigned() && REval.isAllOnesValue()) { + llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx); + if (LEval.isMinSignedValue()) + return ICEDiag(1, E->getLocStart()); + } + } + } + if (Exp->getOpcode() == BinaryOperator::Comma) { + if (Ctx.getLangOptions().C99) { + // C99 6.6p3 introduces a strange edge case: comma can be in an ICE + // if it isn't evaluated. + if (LHSResult.Val == 0 && RHSResult.Val == 0) + return ICEDiag(1, E->getLocStart()); + } else { + // In both C89 and C++, commas in ICEs are illegal. + return ICEDiag(2, E->getLocStart()); + } + } + if (LHSResult.Val >= RHSResult.Val) + return LHSResult; + return RHSResult; + } + case BinaryOperator::LAnd: + case BinaryOperator::LOr: { + ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); + ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); + if (LHSResult.Val == 0 && RHSResult.Val == 1) { + // Rare case where the RHS has a comma "side-effect"; we need + // to actually check the condition to see whether the side + // with the comma is evaluated. + if ((Exp->getOpcode() == BinaryOperator::LAnd) != + (Exp->getLHS()->EvaluateAsInt(Ctx) == 0)) + return RHSResult; + return NoDiag(); + } + + if (LHSResult.Val >= RHSResult.Val) + return LHSResult; + return RHSResult; + } + } + } + case Expr::ImplicitCastExprClass: + case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::CXXConstCastExprClass: { + const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); + if (SubExpr->getType()->isIntegralType()) + return CheckICE(SubExpr, Ctx); + if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) + return NoDiag(); + return ICEDiag(2, E->getLocStart()); + } + case Expr::ConditionalOperatorClass: { + const ConditionalOperator *Exp = cast<ConditionalOperator>(E); + // If the condition (ignoring parens) is a __builtin_constant_p call, + // then only the true side is actually considered in an integer constant + // expression, and it is fully evaluated. This is an important GNU + // extension. See GCC PR38377 for discussion. + if (const CallExpr *CallCE + = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) + if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) { + Expr::EvalResult EVResult; + if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || + !EVResult.Val.isInt()) { + return ICEDiag(2, E->getLocStart()); + } + return NoDiag(); + } + ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); + ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); + ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); + if (CondResult.Val == 2) + return CondResult; + if (TrueResult.Val == 2) + return TrueResult; + if (FalseResult.Val == 2) + return FalseResult; + if (CondResult.Val == 1) + return CondResult; + if (TrueResult.Val == 0 && FalseResult.Val == 0) + return NoDiag(); + // Rare case where the diagnostics depend on which side is evaluated + // Note that if we get here, CondResult is 0, and at least one of + // TrueResult and FalseResult is non-zero. + if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) { + return FalseResult; + } + return TrueResult; + } + case Expr::CXXDefaultArgExprClass: + return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx); + case Expr::ChooseExprClass: { + return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx); + } + } + + // Silence a GCC warning + return ICEDiag(2, E->getLocStart()); +} + +bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, + SourceLocation *Loc, bool isEvaluated) const { + ICEDiag d = CheckICE(this, Ctx); + if (d.Val != 0) { + if (Loc) *Loc = d.Loc; + return false; + } + EvalResult EvalResult; + if (!Evaluate(EvalResult, Ctx)) + 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(); + return true; +} diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 45518e98bc15..d6594cdfd02f 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -145,14 +145,14 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, InnerPolicy.SuppressScope = true; // Nested-name-specifiers are intended to contain minimally-qualified - // types. An actual QualifiedNameType will not occur, since we'll store + // types. An actual ElaboratedType will not occur, since we'll store // just the type that is referred to in the nested-name-specifier (e.g., // a TypedefType, TagType, etc.). However, when we are dealing with // dependent template-id types (e.g., Outer<T>::template Inner<U>), // the type requires its own nested-name-specifier for uniqueness, so we // suppress that nested-name-specifier during printing. - assert(!isa<QualifiedNameType>(T) && - "Qualified name type in nested-name-specifier"); + assert(!isa<ElaboratedType>(T) && + "Elaborated type in nested-name-specifier"); if (const TemplateSpecializationType *SpecType = dyn_cast<TemplateSpecializationType>(T)) { // Print the template name without its corresponding diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp index ade2483722ef..262c4597f846 100644 --- a/lib/AST/RecordLayout.cpp +++ b/lib/AST/RecordLayout.cpp @@ -44,7 +44,9 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx, unsigned fieldcount, uint64_t nonvirtualsize, unsigned nonvirtualalign, - const PrimaryBaseInfo &PrimaryBase, + uint64_t SizeOfLargestEmptySubobject, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseIsVirtual, const BaseOffsetsMapTy& BaseOffsets, const BaseOffsetsMapTy& VBaseOffsets) : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), @@ -55,9 +57,10 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx, memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); } - CXXInfo->PrimaryBase = PrimaryBase; + CXXInfo->PrimaryBase = PrimaryBaseInfo(PrimaryBase, PrimaryBaseIsVirtual); CXXInfo->NonVirtualSize = nonvirtualsize; CXXInfo->NonVirtualAlign = nonvirtualalign; + CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject; CXXInfo->BaseOffsets = BaseOffsets; CXXInfo->VBaseOffsets = VBaseOffsets; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 3782985e5302..983a2874a735 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1,4 +1,4 @@ -//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==// +//=== RecordLayoutBuilder.cpp - Helper class for building record layouts ---==// // // The LLVM Compiler Infrastructure // @@ -7,28 +7,443 @@ // //===----------------------------------------------------------------------===// -#include "RecordLayoutBuilder.h" - #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/Format.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/MathExtras.h" +#include <map> using namespace clang; -ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context) - : Context(Context), Size(0), Alignment(8), Packed(false), - UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false), - NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { } +namespace { + +/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different +/// offsets while laying out a C++ class. +class EmptySubobjectMap { + ASTContext &Context; + + /// Class - The class whose empty entries we're keeping track of. + const CXXRecordDecl *Class; + + /// EmptyClassOffsets - A map from offsets to empty record decls. + typedef llvm::SmallVector<const CXXRecordDecl *, 1> ClassVectorTy; + typedef llvm::DenseMap<uint64_t, ClassVectorTy> EmptyClassOffsetsMapTy; + EmptyClassOffsetsMapTy EmptyClassOffsets; + + /// ComputeEmptySubobjectSizes - Compute the size of the largest base or + /// member subobject that is empty. + void ComputeEmptySubobjectSizes(); + + struct BaseInfo { + const CXXRecordDecl *Class; + bool IsVirtual; + + const CXXRecordDecl *PrimaryVirtualBase; + + llvm::SmallVector<BaseInfo*, 4> Bases; + const BaseInfo *Derived; + }; + + llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> VirtualBaseInfo; + llvm::DenseMap<const CXXRecordDecl *, BaseInfo *> NonVirtualBaseInfo; + + BaseInfo *ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual, + const BaseInfo *Derived); + void ComputeBaseInfo(); + + bool CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, uint64_t Offset); + void UpdateEmptyBaseSubobjects(const BaseInfo *Info, uint64_t Offset); + +public: + /// This holds the size of the largest empty subobject (either a base + /// or a member). Will be zero if the record being built doesn't contain + /// any empty classes. + uint64_t SizeOfLargestEmptySubobject; + + EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class) + : Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) { + ComputeEmptySubobjectSizes(); + + ComputeBaseInfo(); + } + + /// CanPlaceBaseAtOffset - Return whether the given base class can be placed + /// at the given offset. + /// Returns false if placing the record will result in two components + /// (direct or indirect) of the same type having the same offset. + bool CanPlaceBaseAtOffset(const CXXRecordDecl *RD, bool BaseIsVirtual, + uint64_t Offset); +}; + +void EmptySubobjectMap::ComputeEmptySubobjectSizes() { + // Check the bases. + for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), + E = Class->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t EmptySize = 0; + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + if (BaseDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } + + // Check the fields. + for (CXXRecordDecl::field_iterator I = Class->field_begin(), + E = Class->field_end(); I != E; ++I) { + const FieldDecl *FD = *I; + + const RecordType *RT = + Context.getBaseElementType(FD->getType())->getAs<RecordType>(); + + // We only care about record types. + if (!RT) + continue; + + uint64_t EmptySize = 0; + const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl); + if (MemberDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } +} + +EmptySubobjectMap::BaseInfo * +EmptySubobjectMap::ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual, + const BaseInfo *Derived) { + BaseInfo *Info; + + if (IsVirtual) { + BaseInfo *&InfoSlot = VirtualBaseInfo[RD]; + if (InfoSlot) { + assert(InfoSlot->Class == RD && "Wrong class for virtual base info!"); + return InfoSlot; + } + + InfoSlot = new (Context) BaseInfo; + Info = InfoSlot; + } else { + Info = new (Context) BaseInfo; + } + + Info->Class = RD; + Info->IsVirtual = IsVirtual; + Info->Derived = Derived; + Info->PrimaryVirtualBase = 0; + + if (RD->getNumVBases()) { + // Check if this class has a primary virtual base. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + if (Layout.getPrimaryBaseWasVirtual()) { + Info->PrimaryVirtualBase = Layout.getPrimaryBase(); + assert(Info->PrimaryVirtualBase && + "Didn't have a primary virtual base!"); + } + } + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + bool IsVirtual = I->isVirtual(); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + Info->Bases.push_back(ComputeBaseInfo(BaseDecl, IsVirtual, Info)); + } + + return Info; +} + +void EmptySubobjectMap::ComputeBaseInfo() { + for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), + E = Class->bases_end(); I != E; ++I) { + bool IsVirtual = I->isVirtual(); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + BaseInfo *Info = ComputeBaseInfo(BaseDecl, IsVirtual, /*Derived=*/0); + if (IsVirtual) { + // ComputeBaseInfo has already added this base for us. + continue; + } + + // Add the base info to the map of non-virtual bases. + assert(!NonVirtualBaseInfo.count(BaseDecl) && + "Non-virtual base already exists!"); + NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info)); + } +} + +bool +EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseInfo *Info, + uint64_t Offset) { + // Traverse all non-virtual bases. + for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { + BaseInfo* Base = Info->Bases[I]; + if (Base->IsVirtual) + continue; + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class); + + if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset)) + return false; + } + + if (Info->PrimaryVirtualBase) { + BaseInfo *PrimaryVirtualBaseInfo = + VirtualBaseInfo.lookup(Info->PrimaryVirtualBase); + assert(PrimaryVirtualBaseInfo && "Didn't find base info!"); + + if (Info == PrimaryVirtualBaseInfo->Derived) { + if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset)) + return false; + } + } + + // FIXME: Member variables. + return true; +} + +void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseInfo *Info, + uint64_t Offset) { + if (Info->Class->isEmpty()) { + // FIXME: Record that there is an empty class at this offset. + } + + // Traverse all non-virtual bases. + for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { + BaseInfo* Base = Info->Bases[I]; + if (Base->IsVirtual) + continue; + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class); + + UpdateEmptyBaseSubobjects(Base, BaseOffset); + } + + if (Info->PrimaryVirtualBase) { + BaseInfo *PrimaryVirtualBaseInfo = + VirtualBaseInfo.lookup(Info->PrimaryVirtualBase); + assert(PrimaryVirtualBaseInfo && "Didn't find base info!"); + + if (Info == PrimaryVirtualBaseInfo->Derived) + UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset); + } + + // FIXME: Member variables. +} + +bool EmptySubobjectMap::CanPlaceBaseAtOffset(const CXXRecordDecl *RD, + bool BaseIsVirtual, + uint64_t Offset) { + // If we know this class doesn't have any empty subobjects we don't need to + // bother checking. + if (!SizeOfLargestEmptySubobject) + return true; + + BaseInfo *Info; + + if (BaseIsVirtual) + Info = VirtualBaseInfo.lookup(RD); + else + Info = NonVirtualBaseInfo.lookup(RD); + + if (!CanPlaceBaseSubobjectAtOffset(Info, Offset)) + return false; + + UpdateEmptyBaseSubobjects(Info, Offset); + return true; +} + +class RecordLayoutBuilder { + // FIXME: Remove this and make the appropriate fields public. + friend class clang::ASTContext; + + ASTContext &Context; + + EmptySubobjectMap *EmptySubobjects; + + /// Size - The current size of the record layout. + uint64_t Size; + + /// Alignment - The current alignment of the record layout. + unsigned Alignment; + + llvm::SmallVector<uint64_t, 16> FieldOffsets; + + /// Packed - Whether the record is packed or not. + unsigned Packed : 1; + + unsigned IsUnion : 1; + + unsigned IsMac68kAlign : 1; + + /// UnfilledBitsInLastByte - If the last field laid out was a bitfield, + /// this contains the number of bits in the last byte that can be used for + /// an adjacent bitfield if necessary. + unsigned char UnfilledBitsInLastByte; + + /// MaxFieldAlignment - The maximum allowed field alignment. This is set by + /// #pragma pack. + unsigned MaxFieldAlignment; + + /// DataSize - The data size of the record being laid out. + uint64_t DataSize; + + uint64_t NonVirtualSize; + unsigned NonVirtualAlignment; + + /// PrimaryBase - the primary base class (if one exists) of the class + /// we're laying out. + const CXXRecordDecl *PrimaryBase; + + /// PrimaryBaseIsVirtual - Whether the primary base of the class we're laying + /// out is virtual. + bool PrimaryBaseIsVirtual; + + typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy; + + /// Bases - base classes and their offsets in the record. + BaseOffsetsMapTy Bases; + + // VBases - virtual base classes and their offsets in the record. + BaseOffsetsMapTy VBases; + + /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are + /// primary base classes for some other direct or indirect base class. + llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases; + + /// FirstNearlyEmptyVBase - The first nearly empty virtual base class in + /// inheritance graph order. Used for determining the primary base class. + const CXXRecordDecl *FirstNearlyEmptyVBase; + + /// VisitedVirtualBases - A set of all the visited virtual bases, used to + /// avoid visiting virtual bases more than once. + llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; + + /// EmptyClassOffsets - A map from offsets to empty record decls. + typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy; + EmptyClassOffsetsTy EmptyClassOffsets; + + RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects) + : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8), + Packed(false), IsUnion(false), IsMac68kAlign(false), + UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), + NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0), + PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { } + + void Layout(const RecordDecl *D); + void Layout(const CXXRecordDecl *D); + void Layout(const ObjCInterfaceDecl *D); + + void LayoutFields(const RecordDecl *D); + void LayoutField(const FieldDecl *D); + void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize); + void LayoutBitField(const FieldDecl *D); + + /// ComputeEmptySubobjectSizes - Compute the size of the largest base or + /// member subobject that is empty. + void ComputeEmptySubobjectSizes(const CXXRecordDecl *RD); + + /// DeterminePrimaryBase - Determine the primary base of the given class. + void DeterminePrimaryBase(const CXXRecordDecl *RD); + + void SelectPrimaryVBase(const CXXRecordDecl *RD); + + /// IdentifyPrimaryBases - Identify all virtual base classes, direct or + /// indirect, that are primary base classes for some other direct or indirect + /// base class. + void IdentifyPrimaryBases(const CXXRecordDecl *RD); + + bool IsNearlyEmpty(const CXXRecordDecl *RD) const; + + /// LayoutNonVirtualBases - Determines the primary base class (if any) and + /// lays it out. Will then proceed to lay out all non-virtual base clasess. + void LayoutNonVirtualBases(const CXXRecordDecl *RD); + + /// LayoutNonVirtualBase - Lays out a single non-virtual base. + void LayoutNonVirtualBase(const CXXRecordDecl *Base); + + void AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset, + const CXXRecordDecl *MostDerivedClass); + + /// LayoutVirtualBases - Lays out all the virtual bases. + void LayoutVirtualBases(const CXXRecordDecl *RD, + const CXXRecordDecl *MostDerivedClass); + + /// LayoutVirtualBase - Lays out a single virtual base. + void LayoutVirtualBase(const CXXRecordDecl *Base); + + /// LayoutBase - Will lay out a base and return the offset where it was + /// placed, in bits. + uint64_t LayoutBase(const CXXRecordDecl *Base, bool BaseIsVirtual); + + /// canPlaceRecordAtOffset - Return whether a record (either a base class + /// or a field) can be placed at the given offset. + /// Returns false if placing the record will result in two components + /// (direct or indirect) of the same type having the same offset. + bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset, + bool CheckVBases) const; + + /// canPlaceFieldAtOffset - Return whether a field can be placed at the given + /// offset. + bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const; + + /// UpdateEmptyClassOffsets - Called after a record (either a base class + /// or a field) has been placed at the given offset. Will update the + /// EmptyClassOffsets map if the class is empty or has any empty bases or + /// fields. + void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset, + bool UpdateVBases); + + /// UpdateEmptyClassOffsets - Called after a field has been placed at the + /// given offset. + void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset); + + /// InitializeLayout - Initialize record layout for the given record decl. + void InitializeLayout(const Decl *D); + + /// FinishLayout - Fina |