From 71729a81a12da342e4a5a81f0984052b145f1c12 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 4 Jan 2015 20:32:12 +0000 Subject: [PATCH] Remove an assert that's not true on invalid code. r185773 added an assert that checked that a CXXUnresolvedConstructExpr either has a valid rparen, or exactly one argument. This doesn't have to be true for invalid inputs. Convert the assert to an if, and add a test for this case. Found by SLi's afl bot. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225140 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 5 +++-- test/Misc/ast-dump-invalid.cpp | 20 ++++++++++++++++++++ test/SemaCXX/return.cpp | 8 ++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test/Misc/ast-dump-invalid.cpp diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 040fbe7f92..aa33b61d7c 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -2915,8 +2915,9 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY { - assert(RParenLoc.isValid() || NumArgs == 1); - return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd(); + if (!RParenLoc.isValid() && NumArgs > 0) + return getArg(NumArgs - 1)->getLocEnd(); + return RParenLoc; } static bool classof(const Stmt *T) { diff --git a/test/Misc/ast-dump-invalid.cpp b/test/Misc/ast-dump-invalid.cpp new file mode 100644 index 0000000000..3b97cc6540 --- /dev/null +++ b/test/Misc/ast-dump-invalid.cpp @@ -0,0 +1,20 @@ +// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s + +namespace TestInvalidRParenOnCXXUnresolvedConstructExpr { +template +void f(T i, T j) { + return T (i, j; +} +} + +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr +// CHECK-NEXT: `-FunctionTemplateDecl +// CHECK-NEXT: |-TemplateTypeParmDecl +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-ReturnStmt +// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' +// CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 98dbd51f58..8c1664516a 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -112,3 +112,11 @@ namespace ctor_returns_void { ~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}} }; } + +void cxx_unresolved_expr() { + // The use of an undeclared variable tricks clang into building a + // CXXUnresolvedConstructExpr, and the missing ')' gives it an invalid source + // location for its rparen. Check that emitting a diag on the range of the + // expr doesn't assert. + return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{void function 'cxx_unresolved_expr' should not return a value}} expected-error {{use of undeclared identifier 'undeclared'}} +} -- 2.40.0