diff options
Diffstat (limited to 'include/clang/Sema')
-rw-r--r-- | include/clang/Sema/AnalysisBasedWarnings.h | 11 | ||||
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 151 | ||||
-rw-r--r-- | include/clang/Sema/ExternalSemaSource.h | 12 | ||||
-rw-r--r-- | include/clang/Sema/Initialization.h | 17 | ||||
-rw-r--r-- | include/clang/Sema/ParsedTemplate.h | 6 | ||||
-rw-r--r-- | include/clang/Sema/ScopeInfo.h | 17 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 168 |
7 files changed, 327 insertions, 55 deletions
diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h index 0a6656e..8b389b1 100644 --- a/include/clang/Sema/AnalysisBasedWarnings.h +++ b/include/clang/Sema/AnalysisBasedWarnings.h @@ -25,6 +25,9 @@ class FunctionDecl; class ObjCMethodDecl; class QualType; class Sema; +namespace sema { + class FunctionScopeInfo; +} namespace sema { @@ -47,16 +50,14 @@ private: enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD; - void IssueWarnings(Policy P, const Decl *D, QualType BlockTy); public: AnalysisBasedWarnings(Sema &s); - Policy getDefaultPolicy() { return DefaultPolicy; } + void IssueWarnings(Policy P, FunctionScopeInfo *fscope, + const Decl *D, const BlockExpr *blkExpr); - void IssueWarnings(Policy P, const BlockExpr *E); - void IssueWarnings(Policy P, const FunctionDecl *D); - void IssueWarnings(Policy P, const ObjCMethodDecl *D); + Policy getDefaultPolicy() { return DefaultPolicy; } }; }} // end namespace clang::sema diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9c4bb64..64126bd 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -29,10 +29,15 @@ #include "llvm/Support/ErrorHandling.h" namespace clang { + class ASTContext; + class TypeLoc; class LangOptions; class Diagnostic; class IdentifierInfo; + class NamespaceAliasDecl; + class NamespaceDecl; class NestedNameSpecifier; + class NestedNameSpecifierLoc; class Preprocessor; class Declarator; struct TemplateIdAnnotation; @@ -52,9 +57,29 @@ class CXXScopeSpec { SourceRange Range; NestedNameSpecifier *ScopeRep; -public: - CXXScopeSpec() : Range(), ScopeRep() { } + /// \brief Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec. + char *Buffer; + + /// \brief The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize; + + /// \brief The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity; +public: + CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0), + BufferCapacity(0) { } + CXXScopeSpec(const CXXScopeSpec &Other); + CXXScopeSpec &operator=(const CXXScopeSpec &Other); + ~CXXScopeSpec(); + const SourceRange &getRange() const { return Range; } void setRange(const SourceRange &R) { Range = R; } void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } @@ -63,7 +88,87 @@ public: SourceLocation getEndLoc() const { return Range.getEnd(); } NestedNameSpecifier *getScopeRep() const { return ScopeRep; } - void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; } + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TemplateKWLoc The location of the 'template' keyword, if present. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, + SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'identifier::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Identifier The identifier. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + + /// \brief Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// \brief Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// FIXME: This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + SourceRange R); + + /// \brief Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// \brief Retrieve a nested-name-specifier with location information, copied + /// into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; /// No scope specifier. bool isEmpty() const { return !Range.isValid(); } @@ -75,6 +180,15 @@ public: /// A scope specifier is present, and it refers to a real scope. bool isValid() const { return isNotEmpty() && ScopeRep != 0; } + /// \brief Indicate that this nested-name-specifier is invalid. + void SetInvalid(SourceRange R) { + assert(R.isValid() && "Must have a valid source range"); + if (Range.getBegin().isInvalid()) + Range.setBegin(R.getBegin()); + Range.setEnd(R.getEnd()); + ScopeRep = 0; + } + /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). bool isSet() const { return ScopeRep != 0; } @@ -83,6 +197,13 @@ public: Range = SourceRange(); ScopeRep = 0; } + + /// \brief Retrieve the data associated with the source-location information. + char *location_data() const { return Buffer; } + + /// \brief Retrieve the size of the data associated with source-location + /// information. + unsigned location_size() const { return BufferSize; } }; /// DeclSpec - This class captures information about "declaration specifiers", @@ -825,6 +946,16 @@ struct DeclaratorChunk { struct PointerTypeInfo : TypeInfoCommon { /// The type qualifiers: const/volatile/restrict. unsigned TypeQuals : 3; + + /// The location of the const-qualifier, if any. + unsigned ConstQualLoc; + + /// The location of the volatile-qualifier, if any. + unsigned VolatileQualLoc; + + /// The location of the restrict-qualifier, if any. + unsigned RestrictQualLoc; + void destroy() { } }; @@ -1055,12 +1186,18 @@ struct DeclaratorChunk { /// getPointer - Return a DeclaratorChunk for a pointer. /// static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, + SourceLocation ConstQualLoc, + SourceLocation VolatileQualLoc, + SourceLocation RestrictQualLoc, const ParsedAttributes &attrs) { DeclaratorChunk I; - I.Kind = Pointer; - I.Loc = Loc; - I.Ptr.TypeQuals = TypeQuals; - I.Ptr.AttrList = attrs.getList(); + I.Kind = Pointer; + I.Loc = Loc; + I.Ptr.TypeQuals = TypeQuals; + I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); + I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); + I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); + I.Ptr.AttrList = attrs.getList(); return I; } diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 6d7bc63..e2b083e 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -20,6 +20,8 @@ namespace clang { struct ObjCMethodList; class Sema; +class Scope; +class LookupResult; /// \brief An abstract interface that should be implemented by /// external AST sources that also provide information for semantic @@ -47,6 +49,16 @@ public: /// instance and factory methods, respectively, with this selector. virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel); + /// \brief Do last resort, unqualified lookup on a LookupResult that + /// Sema cannot find. + /// + /// \param R a LookupResult that is being recovered. + /// + /// \param S the Scope of the identifier occurrence. + /// + /// \return true to tell Sema to recover using the LookupResult. + virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; } + // isa/cast/dyn_cast support static bool classof(const ExternalASTSource *Source) { return Source->SemaSource; diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index c191565..bdf0d8e 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -467,7 +467,10 @@ public: CAssignment, /// \brief String initialization - StringInit + StringInit, + + /// \brief Array initialization from another array (GNU C extension). + ArrayInit }; /// \brief Describes the kind of a particular step in an initialization @@ -513,7 +516,10 @@ public: SK_StringInit, /// \brief An initialization that "converts" an Objective-C object /// (not a point to an object) to another Objective-C object type. - SK_ObjCObjectConversion + SK_ObjCObjectConversion, + /// \brief Array initialization (from an array rvalue). + /// This is a GNU C extension. + SK_ArrayInit }; /// \brief A single step in the initialization sequence. @@ -563,6 +569,10 @@ public: /// \brief Array must be initialized with an initializer list or a /// string literal. FK_ArrayNeedsInitListOrStringLiteral, + /// \brief Array type mismatch. + FK_ArrayTypeMismatch, + /// \brief Non-constant array initializer + FK_NonConstantArrayInit, /// \brief Cannot resolve the address of an overloaded function. FK_AddressOfOverloadFailed, /// \brief Overloading due to reference initialization failed. @@ -775,6 +785,9 @@ public: /// always a no-op. void AddObjCObjectConversionStep(QualType T); + /// \brief Add an array initialization step. + void AddArrayInitStep(QualType T); + /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 5aa6f47..9e1a616 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -177,6 +177,12 @@ namespace clang { = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + sizeof(ParsedTemplateArgument) * NumArgs); TemplateId->NumArgs = NumArgs; + + // Default-construct parsed template arguments. + ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs(); + for (unsigned I = 0; I != NumArgs; ++I) + new (TemplateArgs + I) ParsedTemplateArgument(); + return TemplateId; } diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b0bb955..51297ae 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_SEMA_SCOPE_INFO_H #include "clang/AST/Type.h" +#include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SetVector.h" @@ -30,6 +31,17 @@ class SwitchStmt; namespace sema { +class PossiblyUnreachableDiag { +public: + PartialDiagnostic PD; + SourceLocation Loc; + const Stmt *stmt; + + PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, + const Stmt *stmt) + : PD(PD), Loc(Loc), stmt(stmt) {} +}; + /// \brief Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { @@ -60,6 +72,11 @@ public: /// block, if there is any chance of applying the named return value /// optimization. llvm::SmallVector<ReturnStmt*, 4> Returns; + + /// \brief A list of PartialDiagnostics created but delayed within the + /// current function scope. These diagnostics are vetted for reachability + /// prior to being emitted. + llvm::SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; void setHasBranchIntoScope() { HasBranchIntoScope = true; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 91d6914..a937398 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -267,6 +267,10 @@ public: /// same list more than once. llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; + /// ParsingInitForAutoVars - a set of declarations with auto types for which + /// we are currently parsing the initializer. + llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars; + /// \brief A mapping from external names to the most recent /// locally-scoped external declaration with that name. /// @@ -684,7 +688,8 @@ public: void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - void PopFunctionOrBlockScope(); + void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0, + const Decl *D = 0, const BlockExpr *blkExpr = 0); sema::FunctionScopeInfo *getCurFunction() const { return FunctionScopes.back(); @@ -856,9 +861,12 @@ public: void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, Decl **Group, unsigned NumDecls); + DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, + bool TypeMayContainAuto = true); void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); @@ -1518,7 +1526,8 @@ public: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl, unsigned DiagID); void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, - ObjCMethodDecl *IntfMethod); + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl, ObjCInterfaceDecl *IDecl); @@ -1883,7 +1892,16 @@ public: void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); void MarkDeclarationsReferencedInExpr(Expr *E); - bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); + + /// \brief Conditionally issue a diagnostic based on the current + /// evaluation context. + /// + /// \param stmt - If stmt is non-null, delay reporting the diagnostic until + /// the function body is parsed, and then do a basic reachability analysis to + /// determine if the statement is reachable. If it is unreachable, the + /// diagnostic will not be emitted. + bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt, + const PartialDiagnostic &PD); // Primary Expressions. SourceRange getExprRange(Expr *E) const; @@ -2573,11 +2591,19 @@ public: CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); bool isUnknownSpecialization(const CXXScopeSpec &SS); - /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the - /// global scope ('::'). - NestedNameSpecifier * - ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc); - + /// \brief The parser has parsed a global nested-name-specifier '::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which will be updated in-place + /// to reflect the parsed nested-name-specifier. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS); + bool isAcceptableNestedNameSpecifier(NamedDecl *SD); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); @@ -2586,43 +2612,97 @@ public: IdentifierInfo &II, ParsedType ObjectType); - NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *ScopeLookupResult, - bool EnteringContext, - bool ErrorRecoveryLookup); - - NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - ParsedType ObjectType, - bool EnteringContext); + bool BuildCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup); + + /// \brief The parser has parsed a nested-name-specifier 'identifier::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param Identifier The identifier preceding the '::'. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param ObjectType The type of the object, if we're parsing + /// nested-name-specifier in a member access expression. + /// + /// \param EnteringContext Whether we're entering the context nominated by + /// this nested-name-specifier. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS); bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - IdentifierInfo &II, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, ParsedType ObjectType, bool EnteringContext); - /// ActOnCXXNestedNameSpecifier - Called during parsing of a - /// nested-name-specifier that involves a template-id, e.g., - /// "foo::bar<int, float>::", and now we need to build a scope - /// specifier. \p SS is empty or the previously parsed nested-name - /// part ("foo::"), \p Type is the already-parsed class template - /// specialization (or other template-id that names a type), \p - /// TypeRange is the source range where the type is located, and \p - /// CCLoc is the location of the trailing '::'. - CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, - ParsedType Type, - SourceRange TypeRange, - SourceLocation CCLoc); - + /// \brief The parser has parsed a nested-name-specifier 'type::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param Type The type, which will be a template specialization + /// type, preceding the '::'. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier(Scope *S, + ParsedType Type, + SourceLocation CCLoc, + CXXScopeSpec &SS); + + /// \brief Given a C++ nested-name-specifier, produce an annotation value + /// that the parser can use later to reconstruct the given + /// nested-name-specifier. + /// + /// \param SS A nested-name-specifier. + /// + /// \returns A pointer containing all of the information in the + /// nested-name-specifier \p SS. + void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); + + /// \brief Given an annotation pointer for a nested-name-specifier, restore + /// the nested-name-specifier structure. + /// + /// \param Annotation The annotation pointer, produced by + /// \c SaveNestedNameSpecifierAnnotation(). + /// + /// \param AnnotationRange The source range corresponding to the annotation. + /// + /// \param SS The nested-name-specifier that will be updated with the contents + /// of the annotation pointer. + void RestoreNestedNameSpecifierAnnotation(void *Annotation, + SourceRange AnnotationRange, + CXXScopeSpec &SS); + bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global @@ -4213,6 +4293,11 @@ public: SubstNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range, const MultiLevelTemplateArgumentList &TemplateArgs); + + NestedNameSpecifierLoc + SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclarationNameInfo SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -4772,7 +4857,8 @@ public: QualType CheckSubtractionOperands( // C99 6.5.6 Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckShiftOperands( // C99 6.5.7 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + bool isCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, bool isRelational); |