From df0325110bb07ab62b808c8db8be2f6eee9b3476 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 12 Mar 2009 22:46:12 +0000 Subject: [PATCH] Implement template instantiation for builtin binary operators git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66835 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.def | 2 +- lib/Sema/Sema.h | 24 +++++++-------- lib/Sema/SemaDecl.cpp | 3 +- lib/Sema/SemaTemplateInstantiate.cpp | 29 +++++++++++++++++- test/SemaTemplate/instantiate-expr-1.cpp | 33 +++++++++++++++++++++ 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index 8408565ce0..0267cfc10b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -770,7 +770,7 @@ DIAG(err_illegal_initializer_type, ERROR, DIAG(err_implicit_empty_initializer, ERROR, "initializer for aggregate with no elements requires explicit braces") DIAG(err_bitfield_has_negative_width, ERROR, - "bit-field %0 has negative width") + "bit-field %0 has negative width (%1)") DIAG(err_bitfield_has_zero_width, ERROR, "bit-field %0 has zero width") DIAG(err_bitfield_width_exceeds_type_size, ERROR, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0ea1be3d7e..913efaf747 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2121,33 +2121,33 @@ public: /// or a null QualType (indicating an error diagnostic was issued). /// type checking binary operators (subroutines of CreateBuiltinBinOp). - inline QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); + QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); QualType CheckPointerToMemberOperands( // C++ 5.5 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect); - inline QualType CheckMultiplyDivideOperands( // C99 6.5.5 + QualType CheckMultiplyDivideOperands( // C99 6.5.5 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckRemainderOperands( // C99 6.5.5 + QualType CheckRemainderOperands( // C99 6.5.5 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckAdditionOperands( // C99 6.5.6 + QualType CheckAdditionOperands( // C99 6.5.6 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckSubtractionOperands( // C99 6.5.6 + QualType CheckSubtractionOperands( // C99 6.5.6 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckShiftOperands( // C99 6.5.7 + QualType CheckShiftOperands( // C99 6.5.7 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckCompareOperands( // C99 6.5.8/9 + QualType CheckCompareOperands( // C99 6.5.8/9 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isRelational); - inline QualType CheckBitwiseOperands( // C99 6.5.[10...12] + QualType CheckBitwiseOperands( // C99 6.5.[10...12] Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); - inline QualType CheckLogicalOperands( // C99 6.5.[13,14] + QualType CheckLogicalOperands( // C99 6.5.[13,14] Expr *&lex, Expr *&rex, SourceLocation OpLoc); // CheckAssignmentOperands is used for both simple and compound assignment. // For simple assignment, pass both expressions and a null converted type. // For compound assignment, pass both expressions and the converted type. - inline QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] + QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType); - inline QualType CheckCommaOperands( // C99 6.5.17 + QualType CheckCommaOperands( // C99 6.5.17 Expr *lex, Expr *&rex, SourceLocation OpLoc); - inline QualType CheckConditionalOperands( // C99 6.5.15 + QualType CheckConditionalOperands( // C99 6.5.15 Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); /// type checking for vector binary operators. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bedf05ed35..f3983aee45 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3379,7 +3379,8 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; if (Value.isNegative()) - return Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName; + return Diag(FieldLoc, diag::err_bitfield_has_negative_width) + << FieldName << Value.toString(10); if (!FieldTy->isDependentType()) { uint64_t TypeSize = Context.getTypeSize(FieldTy); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 6252e29e56..4b98d30b47 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -576,9 +576,13 @@ namespace { Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E); Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E); Sema::OwningExprResult VisitParenExpr(ParenExpr *E); + Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E); // Base case. I'm supposed to ignore this. - Sema::OwningExprResult VisitStmt(Stmt *) { return SemaRef.ExprError(); } + Sema::OwningExprResult VisitStmt(Stmt *) { + assert(false && "Cannot instantiate this kind of expression"); + return SemaRef.ExprError(); + } }; } @@ -618,6 +622,29 @@ TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) { (Expr *)SubExpr.release())); } +Sema::OwningExprResult +TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) { + Sema::OwningExprResult LHS = Visit(E->getLHS()); + if (LHS.isInvalid()) + return SemaRef.ExprError(); + + Sema::OwningExprResult RHS = Visit(E->getRHS()); + if (RHS.isInvalid()) + return SemaRef.ExprError(); + + Sema::OwningExprResult Result + = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), + E->getOpcode(), + (Expr *)LHS.get(), + (Expr *)RHS.get()); + if (Result.isInvalid()) + return SemaRef.ExprError(); + + LHS.release(); + RHS.release(); + return move(Result); +} + Sema::OwningExprResult Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp index 060c1b510c..6fceddf05b 100644 --- a/test/SemaTemplate/instantiate-expr-1.cpp +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -10,3 +10,36 @@ void test_Bitfields(Bitfields<0, 5> *b) { (void)sizeof(Bitfields<10, 5>); (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}} } + +template +struct BitfieldPlus { + int bitfield : I + J; // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldPlus() { + (void)sizeof(BitfieldPlus<0, 1>); + (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldPlus<-5, 5>' requested here}} +} + +template +struct BitfieldMinus { + int bitfield : I - J; // expected-error{{bit-field 'bitfield' has negative width (-1)}} \ + // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldMinus() { + (void)sizeof(BitfieldMinus<5, 1>); + (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<0, 1>' requested here}} + (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<5, 5>' requested here}} +} + +template +struct BitfieldDivide { + int bitfield : I / J; // expected-error{{expression is not an integer constant expression}} \ + // expected-note{{division by zero}} +}; + +void test_BitfieldDivide() { + (void)sizeof(BitfieldDivide<5, 1>); + (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}} +} -- 2.40.0