summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-06-11 17:19:42 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-06-11 17:19:42 +0000
commit7a614d8380297fcd2bc23986241905d97222948c (patch)
treebcbfe125e7a2dccada57451970279902a4cfe486 /include
parent27f45236005d9dd2bbbfeb1682eb349cb8b6998b (diff)
Implement support for C++11 in-class initialization of non-static data members.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132878 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/Decl.h60
-rw-r--r--include/clang/AST/DeclCXX.h18
-rw-r--r--include/clang/AST/DeclObjC.h4
-rw-r--r--include/clang/AST/Type.h1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td11
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--include/clang/Basic/ExceptionSpecificationType.h13
-rw-r--r--include/clang/Parse/Parser.h42
-rw-r--r--include/clang/Sema/DeclSpec.h27
-rw-r--r--include/clang/Sema/Scope.h7
-rw-r--r--include/clang/Sema/Sema.h35
11 files changed, 192 insertions, 32 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e1dad644c9..d993d345ef 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1953,20 +1953,33 @@ class FieldDecl : public DeclaratorDecl {
bool Mutable : 1;
mutable unsigned CachedFieldIndex : 31;
- Expr *BitWidth;
+ /// \brief A pointer to either the in-class initializer for this field (if
+ /// the boolean value is false), or the bit width expression for this bit
+ /// field (if the boolean value is true).
+ ///
+ /// We can safely combine these two because in-class initializers are not
+ /// permitted for bit-fields.
+ ///
+ /// If the boolean is false and the initializer is null, then this field has
+ /// an in-class initializer which has not yet been parsed and attached.
+ llvm::PointerIntPair<Expr *, 1, bool> InitializerOrBitWidth;
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable)
+ QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+ bool HasInit)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
- Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
+ Mutable(Mutable), CachedFieldIndex(0),
+ InitializerOrBitWidth(BW, !HasInit) {
+ assert(!(BW && HasInit) && "got initializer for bitfield");
}
public:
static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
+ TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+ bool HasInit);
/// getFieldIndex - Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
@@ -1979,10 +1992,12 @@ public:
void setMutable(bool M) { Mutable = M; }
/// isBitfield - Determines whether this field is a bitfield.
- bool isBitField() const { return BitWidth != NULL; }
+ bool isBitField() const {
+ return InitializerOrBitWidth.getInt() && InitializerOrBitWidth.getPointer();
+ }
/// @brief Determines whether this is an unnamed bitfield.
- bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
+ bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
/// isAnonymousStructOrUnion - Determines whether this field is a
/// representative for an anonymous struct or union. Such fields are
@@ -1990,8 +2005,37 @@ public:
/// store the data for the anonymous union or struct.
bool isAnonymousStructOrUnion() const;
- Expr *getBitWidth() const { return BitWidth; }
- void setBitWidth(Expr *BW) { BitWidth = BW; }
+ Expr *getBitWidth() const {
+ return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
+ }
+ void setBitWidth(Expr *BW) {
+ assert(!InitializerOrBitWidth.getPointer() &&
+ "bit width or initializer already set");
+ InitializerOrBitWidth.setPointer(BW);
+ InitializerOrBitWidth.setInt(1);
+ }
+
+ /// hasInClassInitializer - Determine whether this member has a C++0x in-class
+ /// initializer.
+ bool hasInClassInitializer() const {
+ return !InitializerOrBitWidth.getInt();
+ }
+ /// getInClassInitializer - Get the C++0x in-class initializer for this
+ /// member, or null if one has not been set. If a valid declaration has an
+ /// in-class initializer, but this returns null, then we have not parsed and
+ /// attached it yet.
+ Expr *getInClassInitializer() const {
+ return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0;
+ }
+ /// setInClassInitializer - Set the C++0x in-class initializer for this member.
+ void setInClassInitializer(Expr *Init);
+ /// removeInClassInitializer - Remove the C++0x in-class initializer from this
+ /// member.
+ void removeInClassInitializer() {
+ assert(!InitializerOrBitWidth.getInt() && "no initializer to remove");
+ InitializerOrBitWidth.setPointer(0);
+ InitializerOrBitWidth.setInt(1);
+ }
/// getParent - Returns the parent of this field declaration, which
/// is the struct in which this method is defined.
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 096ace7128..42a12eb5a3 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1378,6 +1378,8 @@ class CXXCtorInitializer {
/// \brief The argument used to initialize the base or member, which may
/// end up constructing an object (when multiple arguments are involved).
+ /// If 0, this is a field initializer, and the in-class member initializer
+ /// will be used.
Stmt *Init;
/// LParenLoc - Location of the left paren of the ctor-initializer.
@@ -1452,6 +1454,13 @@ public:
return Initializee.is<IndirectFieldDecl*>();
}
+ /// isInClassMemberInitializer - Returns true when this initializer is an
+ /// implicit ctor initializer generated for a field with an initializer
+ /// defined on the member declaration.
+ bool isInClassMemberInitializer() const {
+ return !Init;
+ }
+
/// isDelegatingInitializer - Returns true when this initializer is creating
/// a delegating constructor.
bool isDelegatingInitializer() const {
@@ -1580,7 +1589,14 @@ public:
reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
}
- Expr *getInit() const { return static_cast<Expr *>(Init); }
+ /// \brief Get the initializer. This is 0 if this is an in-class initializer
+ /// for a non-static data member which has not yet been parsed.
+ Expr *getInit() const {
+ if (!Init)
+ return getAnyMember()->getInClassInitializer();
+
+ return static_cast<Expr*>(Init);
+ }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 0e698607db..74ceb43c71 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -724,7 +724,7 @@ private:
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
bool synthesized)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
- /*Mutable=*/false),
+ /*Mutable=*/false, /*HasInit=*/false),
NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
public:
@@ -779,7 +779,7 @@ private:
QualType T, Expr *BW)
: FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
/*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
- BW, /*Mutable=*/false) {}
+ BW, /*Mutable=*/false, /*HasInit=*/false) {}
public:
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7dc672a41a..77633831ff 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -2604,6 +2604,7 @@ public:
}
bool isNothrow(ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
+ assert(EST != EST_Delayed);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
if (EST != EST_ComputedNoexcept)
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index efac2b7d77..fb1c909508 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -193,6 +193,8 @@ def ext_ref_qualifier : ExtWarn<
"reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
def ext_inline_namespace : ExtWarn<
"inline namespaces are a C++0x feature">, InGroup<CXX0x>;
+def err_generalized_initializer_lists : Error<
+ "generalized initializer lists are a C++0x extension unsupported in Clang">;
def ext_generalized_initializer_lists : ExtWarn<
"generalized initializer lists are a C++0x extension unsupported in Clang">,
InGroup<CXX0x>;
@@ -444,6 +446,15 @@ def warn_defaulted_function_accepted_as_extension: ExtWarn<
"defaulted function definition accepted as a C++0x extension">,
InGroup<CXX0x>;
+// C++0x in-class member initialization
+def warn_nonstatic_member_init_accepted_as_extension: ExtWarn<
+ "in-class initialization of non-static data member accepted as a C++0x extension">,
+ InGroup<CXX0x>;
+def err_bitfield_member_init: Error<
+ "bitfield member cannot have an in-class initializer">;
+def err_incomplete_array_member_init: Error<
+ "array bound cannot be deduced from an in-class initializer">;
+
// C++0x alias-declaration
def ext_alias_declaration : ExtWarn<
"alias declarations accepted as a C++0x extension">, InGroup<CXX0x>;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 7890aefc50..5cfa61b397 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -589,6 +589,8 @@ def warn_missing_exception_specification : Warning<
"%0 is missing exception specification '%1'">;
def err_noexcept_needs_constant_expression : Error<
"argument to noexcept specifier must be a constant expression">;
+def err_exception_spec_unknown : Error<
+ "exception specification is not available until end of class definition">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
@@ -973,8 +975,8 @@ def err_illegal_decl_array_of_auto : Error<
def err_new_array_of_auto : Error<
"cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
- "'auto' not allowed %select{in function prototype|in struct member"
- "|in union member|in class member|in exception declaration"
+ "'auto' not allowed %select{in function prototype|in non-static struct member"
+ "|in non-static union member|in non-static class member|in exception declaration"
"|in template parameter|in block literal|in template argument"
"|in typedef|in type alias|in function return type|here}0">;
def err_auto_var_requires_init : Error<
diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h
index aecf6eb269..98cfd297ad 100644
--- a/include/clang/Basic/ExceptionSpecificationType.h
+++ b/include/clang/Basic/ExceptionSpecificationType.h
@@ -18,12 +18,13 @@ namespace clang {
/// \brief The various types of exception specifications that exist in C++0x.
enum ExceptionSpecificationType {
- EST_None, ///< no exception specification
- EST_DynamicNone, ///< throw()
- EST_Dynamic, ///< throw(T1, T2)
- EST_MSAny, ///< Microsoft throw(...) extension
- EST_BasicNoexcept, ///< noexcept
- EST_ComputedNoexcept ///< noexcept(expression)
+ EST_None, ///< no exception specification
+ EST_DynamicNone, ///< throw()
+ EST_Dynamic, ///< throw(T1, T2)
+ EST_MSAny, ///< Microsoft throw(...) extension
+ EST_BasicNoexcept, ///< noexcept
+ EST_ComputedNoexcept, ///< noexcept(expression)
+ EST_Delayed ///< not known yet
};
inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 680b788dce..e4cdc27c43 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -580,6 +580,18 @@ private:
/// ExitScope - Pop a scope off the scope stack.
void ExitScope();
+ /// \brief RAII object used to modify the scope flags for the current scope.
+ class ParseScopeFlags {
+ Scope *CurScope;
+ unsigned OldFlags;
+ ParseScopeFlags(const ParseScopeFlags &); // do not implement
+ void operator=(const ParseScopeFlags &); // do not implement
+
+ public:
+ ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true);
+ ~ParseScopeFlags();
+ };
+
//===--------------------------------------------------------------------===//
// Diagnostic Emission and Error recovery.
@@ -621,8 +633,8 @@ private:
/// - function bodies
/// - default arguments
/// - exception-specifications (TODO: C++0x)
- /// - and brace-or-equal-initializers (TODO: C++0x)
- /// for non-static data members (including such things in nested classes)."
+ /// - and brace-or-equal-initializers for non-static data members
+ /// (including such things in nested classes)."
/// LateParsedDeclarations build the tree of those elements so they can
/// be parsed after parsing the top-level class.
class LateParsedDeclaration {
@@ -630,6 +642,7 @@ private:
virtual ~LateParsedDeclaration();
virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMemberInitializers();
virtual void ParseLexedMethodDefs();
};
@@ -641,6 +654,7 @@ private:
virtual ~LateParsedClass();
virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMemberInitializers();
virtual void ParseLexedMethodDefs();
private:
@@ -714,6 +728,25 @@ private:
llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
};
+ /// LateParsedMemberInitializer - An initializer for a non-static class data
+ /// member whose parsing must to be delayed until the class is completely
+ /// defined (C++11 [class.mem]p2).
+ struct LateParsedMemberInitializer : public LateParsedDeclaration {
+ LateParsedMemberInitializer(Parser *P, Decl *FD)
+ : Self(P), Field(FD) { }
+
+ virtual void ParseLexedMemberInitializers();
+
+ Parser *Self;
+
+ /// Field - The field declaration.
+ Decl *Field;
+
+ /// CachedTokens - The sequence of tokens that comprises the initializer,
+ /// including any leading '='.
+ CachedTokens Toks;
+ };
+
/// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
/// C++ class, its method declarations that contain parts that won't be
/// parsed until after the definition is completed (C++ [class.mem]p2),
@@ -974,10 +1007,13 @@ private:
Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo,
const VirtSpecifiers& VS, ExprResult& Init);
+ void ParseCXXNonStaticMemberInitializer(Decl *VarD);
void ParseLexedMethodDeclarations(ParsingClass &Class);
void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
void ParseLexedMethodDefs(ParsingClass &Class);
void ParseLexedMethodDef(LexedMethod &LM);
+ void ParseLexedMemberInitializers(ParsingClass &Class);
+ void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
CachedTokens &Toks,
bool StopAtSemi = true,
@@ -1755,6 +1791,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
bool SuppressDeclarations = false);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
Decl *TagDecl);
+ ExprResult ParseCXXMemberInitializer(bool IsFunction,
+ SourceLocation &EqualLoc);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
ParsingDeclRAIIObject *DiagsFromTParams = 0);
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index be1f5f8c79..7ce4e00943 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -1078,8 +1078,8 @@ struct DeclaratorChunk {
/// If this is an invalid location, there is no ref-qualifier.
unsigned RefQualifierLoc;
- /// \brief When ExceptionSpecType isn't EST_None, the location of the
- /// keyword introducing the spec.
+ /// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the
+ /// location of the keyword introducing the spec.
unsigned ExceptionSpecLoc;
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
@@ -1616,6 +1616,29 @@ public:
DeclTypeInfo.erase(DeclTypeInfo.begin());
}
+ /// isArrayOfUnknownBound - This method returns true if the declarator
+ /// is a declarator for an array of unknown bound (looking through
+ /// parentheses).
+ bool isArrayOfUnknownBound() const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ switch (DeclTypeInfo[i].Kind) {
+ case DeclaratorChunk::Paren:
+ continue;
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ return false;
+ case DeclaratorChunk::Array:
+ return !DeclTypeInfo[i].Arr.NumElts;
+ }
+ llvm_unreachable("Invalid type chunk");
+ return false;
+ }
+ return false;
+ }
+
/// isFunctionDeclarator - This method returns true if the declarator
/// is a function declarator (looking through parentheses).
/// If true is returned, then the reference type parameter idx is
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index 6588a1d92d..7514633c0e 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -79,7 +79,12 @@ public:
ObjCMethodScope = 0x400,
/// SwitchScope - This is a scope that corresponds to a switch statement.
- SwitchScope = 0x800
+ SwitchScope = 0x800,
+
+ /// ThisScope - This is the scope of a struct/union/class definition,
+ /// outside of any member function definition, where 'this' is nonetheless
+ /// usable.
+ ThisScope = 0x1000
};
private:
/// The parent scope for this scope. This is null for the translation-unit
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index bb3ec2dbed..6dd0d3ceab 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1144,13 +1144,13 @@ public:
Declarator &D, Expr *BitfieldWidth);
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
- Declarator &D, Expr *BitfieldWidth,
+ Declarator &D, Expr *BitfieldWidth, bool HasInit,
AccessSpecifier AS);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
RecordDecl *Record, SourceLocation Loc,
- bool Mutable, Expr *BitfieldWidth,
+ bool Mutable, Expr *BitfieldWidth, bool HasInit,
SourceLocation TSSL,
AccessSpecifier AS, NamedDecl *PrevDecl,
Declarator *D = 0);
@@ -2612,6 +2612,13 @@ public:
// Then a throw(collected exceptions)
// Finally no specification.
// throw(...) is used instead if any called function uses it.
+ //
+ // If this exception specification cannot be known yet (for instance,
+ // because this is the exception specification for a defaulted default
+ // constructor and we haven't finished parsing the deferred parts of the
+ // class yet), the C++0x standard does not specify how to behave. We
+ // record this as an 'unknown' exception specification, which overrules
+ // any other specification (even 'none', to keep this rule simple).
ExceptionSpecificationType ComputedEST;
llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
llvm::SmallVector<QualType, 4> Exceptions;
@@ -2644,6 +2651,15 @@ public:
/// \brief Integrate another called method into the collected data.
void CalledDecl(CXXMethodDecl *Method);
+ /// \brief Integrate an invoked expression into the collected data.
+ void CalledExpr(Expr *E);
+
+ /// \brief Specify that the exception specification can't be detemined yet.
+ void SetDelayed() {
+ ClearExceptions();
+ ComputedEST = EST_Delayed;
+ }
+
FunctionProtoType::ExtProtoInfo getEPI() const {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = getExceptionSpecType();
@@ -2836,10 +2852,9 @@ public:
//// ActOnCXXThis - Parse 'this' pointer.
ExprResult ActOnCXXThis(SourceLocation loc);
- /// tryCaptureCXXThis - Try to capture a 'this' pointer. Returns a
- /// pointer to an instance method whose 'this' pointer is
- /// capturable, or null if this is not possible.
- CXXMethodDecl *tryCaptureCXXThis();
+ /// getAndCaptureCurrentThisType - Try to capture a 'this' pointer. Returns
+ /// the type of the 'this' pointer, or a null type if this is not possible.
+ QualType getAndCaptureCurrentThisType();
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -3238,7 +3253,10 @@ public:
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
- Expr *Init, bool IsDefinition);
+ Expr *Init, bool HasDeferredInit,
+ bool IsDefinition);
+ void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
+ Expr *Init);
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -3342,8 +3360,9 @@ public:
void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
- void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnFinishDelayedMemberInitializers(Decl *Record);
void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true);
bool IsInsideALocalClassWithinATemplateFunction();