Implement template instantiation for builtin binary operators
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66835 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index 8408565..0267cfc 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -770,7 +770,7 @@
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 0ea1be3..913efaf 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2121,33 +2121,33 @@
/// 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 bedf05e..f3983ae 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3379,7 +3379,8 @@
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 6252e29..4b98d30 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -576,9 +576,13 @@
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();
+ }
};
}
@@ -619,6 +623,29 @@
}
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) {
TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);
diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp
index 060c1b5..6fceddf 100644
--- a/test/SemaTemplate/instantiate-expr-1.cpp
+++ b/test/SemaTemplate/instantiate-expr-1.cpp
@@ -10,3 +10,36 @@
(void)sizeof(Bitfields<10, 5>);
(void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}}
}
+
+template<int I, int J>
+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<int I, int J>
+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<int I, int J>
+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}}
+}