djtodoro updated this revision to Diff 188110.
djtodoro added a comment.
Herald added a subscriber: jdoerfert.
- Handle all kinds of expressions when mark a param's modification
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D58035/new/
https://reviews.llvm.org/D58035
Files:
include/clang/AST/Decl.h
lib/CodeGen/CGDebugInfo.cpp
lib/Sema/SemaExpr.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/CodeGen/dbginfo-var-change-templates.cpp
test/CodeGen/debug-info-varchange.c
Index: test/CodeGen/debug-info-varchange.c
===================================================================
--- /dev/null
+++ test/CodeGen/debug-info-varchange.c
@@ -0,0 +1,35 @@
+// RUN: %clang -femit-param-entry-values -emit-llvm -S -g %s -o - | FileCheck %s
+
+// CHECK: !DILocalVariable(name: "a", arg: 1, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified)
+// CHECK: !DILocalVariable(name: "b", arg: 2, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}})
+// CHECK: !DILocalVariable(name: "test_s", arg: 3, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified)
+// CHECK: !DILocalVariable(name: "test_s2", arg: 4, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}})
+// CHECK: !DILocalVariable(name: "x", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}})
+// CHECK: !DILocalVariable(name: "y", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}})
+
+typedef struct s {
+ int m;
+ int n;
+}S;
+
+void foo (int a, int b,
+ S test_s, S test_s2)
+{
+ b++;
+ b = a + 1;
+ if (b>4)
+ test_s2.m = 434;
+}
+
+int main()
+{
+ S test_s = {4, 5};
+
+ int x = 5;
+ int y = 6;
+
+ foo(x , y, test_s, test_s);
+
+ return 0;
+}
+
Index: test/CodeGen/dbginfo-var-change-templates.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/dbginfo-var-change-templates.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang -femit-param-entry-values -emit-llvm -S -g %s -o - | FileCheck %s
+// CHECK: !DILocalVariable(name: "a", arg: 1, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}})
+// CHECK: !DILocalVariable(name: "b", arg: 2, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified)
+
+template <class T>
+__attribute__((noinline))
+T GetMin (T a, T b) {
+ T result;
+ ++a;
+ result = (a < b) ? a : b;
+ return result;
+}
+
+int baa () {
+ int i=5, j=6, k;
+ k=GetMin<int>(i,j);
+
+ if (i == k)
+ ++k;
+ else
+ --k;
+
+ return k;
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -1033,6 +1033,7 @@
Record.push_back(D->hasUninstantiatedDefaultArg());
if (D->hasUninstantiatedDefaultArg())
Record.AddStmt(D->getUninstantiatedDefaultArg());
+ Record.push_back(D->isArgumentKnownToBeModified());
Code = serialization::DECL_PARM_VAR;
assert(!D->isARCPseudoStrong()); // can be true of ImplicitParamDecl
@@ -1046,6 +1047,7 @@
!D->isImplicit() &&
!D->isUsed(false) &&
!D->isInvalidDecl() &&
+ !D->isArgumentKnownToBeModified() &&
!D->isReferenced() &&
D->getAccess() == AS_none &&
!D->isModulePrivate() &&
@@ -2011,6 +2013,7 @@
Abv->Add(BitCodeAbbrevOp(0)); // KNRPromoted
Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg
Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg
+ Abv->Add(BitCodeAbbrevOp(0)); // IsArgumentKnownToBeModified
// Type Source Info
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -1441,7 +1441,7 @@
PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt();
if (Record.readInt()) // hasUninstantiatedDefaultArg.
PD->setUninstantiatedDefaultArg(Record.readExpr());
-
+ PD->ParmVarDeclBits.IsArgumentKnownToBeModified = Record.readInt();
// FIXME: If this is a redeclaration of a function from another module, handle
// inheritance of default arguments.
}
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
@@ -11276,6 +11277,30 @@
DiagnoseConstAssignment(S, E, Loc);
}
+/// Traverse an expression and find declaration ref, if any.
+static bool HasDeclRef(const Expr *E, const DeclRefExpr *&DeclRef) {
+ if ((DeclRef = dyn_cast_or_null<DeclRefExpr>(E)))
+ return true;
+
+ for (const Stmt *SubStmt : E->children())
+ if (const auto *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
+ if (HasDeclRef(SubExpr, DeclRef))
+ return true;
+
+ return false;
+}
+
+/// Argument's value might be modified, so update the info.
+static void EmitArgumentsValueModification(Expr *E) {
+ const DeclRefExpr *LHSDeclRef;
+ if (HasDeclRef(E, LHSDeclRef)) {
+ const ValueDecl *Decl = LHSDeclRef->getDecl();
+ if (const auto *PD = dyn_cast_or_null<ParmVarDecl>(Decl))
+ if (!PD->isArgumentKnownToBeModified())
+ const_cast<ParmVarDecl*>(PD)->setIsArgumentKnownToBeModified();
+ }
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -11288,8 +11313,10 @@
&Loc);
if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
- if (IsLV == Expr::MLV_Valid)
+ if (IsLV == Expr::MLV_Valid) {
+ EmitArgumentsValueModification(E);
return false;
+ }
unsigned DiagID = 0;
bool NeedType = false;
@@ -11341,6 +11368,7 @@
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
// We need to preserve the AST regardless, so migration tool
// can do its job.
+ EmitArgumentsValueModification(E);
return false;
}
}
@@ -11381,8 +11409,13 @@
break;
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
- return S.RequireCompleteType(Loc, E->getType(),
- diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
+ {
+ bool NeedCompleteType = S.RequireCompleteType(Loc, E->getType(),
+ diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
+ if (!NeedCompleteType)
+ EmitArgumentsValueModification(E);
+ return NeedCompleteType;
+ }
case Expr::MLV_DuplicateVectorComponents:
DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -3778,6 +3778,12 @@
if (VD->isImplicit())
Flags |= llvm::DINode::FlagArtificial;
+ if (const auto *PD = dyn_cast<ParmVarDecl>(VD)) {
+ auto &CGOpts = CGM.getCodeGenOpts();
+ if (CGOpts.EnableParamEntryValues && !PD->isArgumentKnownToBeModified())
+ Flags |= llvm::DINode::FlagArgumentNotModified;
+ }
+
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType());
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -905,6 +905,9 @@
/// Whether this parameter is an ObjC method parameter or not.
unsigned IsObjCMethodParam : 1;
+ /// Whether this parameter is known to be modified throughout a function.
+ unsigned IsArgumentKnownToBeModified : 1;
+
/// If IsObjCMethodParam, a Decl::ObjCDeclQualifier.
/// Otherwise, the number of function parameter scopes enclosing
/// the function parameter scope in which this parameter was
@@ -1560,6 +1563,7 @@
assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
assert(ParmVarDeclBits.IsKNRPromoted == false);
assert(ParmVarDeclBits.IsObjCMethodParam == false);
+ assert(ParmVarDeclBits.IsArgumentKnownToBeModified == false);
setDefaultArg(DefArg);
}
@@ -1593,6 +1597,13 @@
return ParmVarDeclBits.IsObjCMethodParam;
}
+ bool isArgumentKnownToBeModified() const {
+ return ParmVarDeclBits.IsArgumentKnownToBeModified;
+ }
+ void setIsArgumentKnownToBeModified() {
+ ParmVarDeclBits.IsArgumentKnownToBeModified = true;
+ }
+
unsigned getFunctionScopeDepth() const {
if (ParmVarDeclBits.IsObjCMethodParam) return 0;
return ParmVarDeclBits.ScopeDepthOrObjCQuals;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits