1bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov/* Copyright (c) 2008-2010, Google Inc.
2bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * All rights reserved.
3bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *
4bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * Redistribution and use in source and binary forms, with or without
5bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * modification, are permitted provided that the following conditions are
6bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * met:
7bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *
8bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *     * Redistributions of source code must retain the above copyright
9bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * notice, this list of conditions and the following disclaimer.
10bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *     * Neither the name of Google Inc. nor the names of its
11bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * contributors may be used to endorse or promote products derived from
12bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * this software without specific prior written permission.
13bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *
14bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov */
26bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
27bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// This file is part of ThreadSanitizer, a dynamic data race detector.
28bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Author: Evgeniy Stepanov.
29bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
30bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// This file contains the parser for valgrind-compatible suppressions.
31bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
32bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "suppressions.h"
33bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
34bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// TODO(eugenis): convert checks to warning messages.
35bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// TODO(eugenis): write tests for incorrect syntax.
36bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
37bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovenum LocationType {
38bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  LT_STAR,  // ...
39bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  LT_OBJ,  // obj:
40bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  LT_FUN,  // fun:
41bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
42bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
43bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct Location {
44bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  LocationType type;
45bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string name;
46bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
47bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
48bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct StackTraceTemplate {
49bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  vector<Location> locations;
50bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
51bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
52bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct Suppression {
53bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string name;
54bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  set<string> tools;
55bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string warning_name;
56bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // Extra information available for some suppression types.
57bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // ex.: Memcheck:Param
58bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string extra;
59bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  vector<StackTraceTemplate> templates;
60bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
61bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
62bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovclass Parser {
63bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov public:
64bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  explicit Parser(const string &str)
65bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      : buffer_(str), next_(buffer_.c_str()),
66bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        end_(buffer_.c_str() + buffer_.size()), line_no_(0), error_(false) {}
67bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
68bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool NextSuppression(Suppression* suppression);
69bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool GetError();
70bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string GetErrorString();
71bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  int GetLineNo();
72bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
73bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov private:
74bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool Eof() { return next_ >= end_; }
75bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string NextLine();
76bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string NextLineSkipComments();
77bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  void PutBackSkipComments(string line);
78bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool ParseSuppressionToolsLine(Suppression* supp, string line);
79bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool IsExtraLine(string line);
80bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool ParseStackTraceLine(StackTraceTemplate* trace, string line);
81bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool NextStackTraceTemplate(StackTraceTemplate* trace, bool* last);
82bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
83bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  void SetError(string desc);
84bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
85bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const string& buffer_;
86bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const char* next_;
87bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const char* end_;
88bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  stack<string> put_back_stack_;
89bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
90bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  int line_no_;
91bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool error_;
92bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string error_string_;
93bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
94bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
95bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define PARSER_CHECK(cond, desc) do {\
96bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (!(cond)) {\
97bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      SetError(desc);\
98bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return false;\
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }} while ((void)0, 0)
100bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
101bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid Parser::SetError(string desc) {
102bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  error_ = true;
103bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  error_string_ = desc;
104bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
105bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
106bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::GetError() {
107bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return error_;
108bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
109bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
110bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring Parser::GetErrorString() {
111bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return error_string_;
112bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
113bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
114bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint Parser::GetLineNo() {
115bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return line_no_;
116bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
117bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
118bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring Parser::NextLine() {
119bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const char* first = next_;
120bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (!Eof() && *next_ != '\n') {
121bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    ++next_;
122bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
123bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string line(first, next_ - first);
124bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (*next_ == '\n') {
125bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    ++next_;
126bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
127bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  ++line_no_;
128bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return line;
129bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
130bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
131bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring Parser::NextLineSkipComments() {
132bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string line;
133bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (!put_back_stack_.empty()) {
134bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    line = put_back_stack_.top();
135bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    put_back_stack_.pop();
136bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return line;
137bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
138bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (!Eof()) {
139bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    line = NextLine();
140bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    // Skip empty lines.
141bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (line.empty())
142bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      continue;
143bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    // Skip comments.
144bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (line[0] == '#')
145bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      continue;
146bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const char* p = line.c_str();
147bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const char* e = p + line.size();
148bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    // Strip whitespace.
149bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    while (p < e && (*p == ' ' || *p == '\t'))
150bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      ++p;
151bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (p >= e)
152bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      continue;
153bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const char* last = e - 1;
154bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    while (last > p && (*last == ' ' || *last == '\t'))
155bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      --last;
156bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return string(p, last - p + 1);
157bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
158bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return "";
159bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
160bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
161bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid Parser::PutBackSkipComments(string line) {
162bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  put_back_stack_.push(line);
163bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
164bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
165bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::ParseSuppressionToolsLine(Suppression* supp, string line) {
166bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  size_t idx = line.find(':');
167bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(idx != string::npos, "expected ':' in tools line");
168bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string s1 = line.substr(0, idx);
169bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string s2 = line.substr(idx + 1);
170bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(!s1.empty(), "expected non-empty tool(s) name");
171bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(!s2.empty(), "expected non-empty warning name");
172bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  size_t idx2;
173bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while ((idx2 = s1.find(',')) != string::npos) {
174bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    supp->tools.insert(s1.substr(0, idx2));
175bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    s1.erase(0, idx2 + 1);
176bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
177bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  supp->tools.insert(s1);
178bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  supp->warning_name = s2;
179bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return true;
180bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
181bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
182bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::ParseStackTraceLine(StackTraceTemplate* trace, string line) {
183bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line == "...") {
184bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    Location location = {LT_STAR, ""};
185bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    trace->locations.push_back(location);
186bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return true;
187bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  } else {
188bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    size_t idx = line.find(':');
189bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    PARSER_CHECK(idx != string::npos, "expected ':' in stack trace line");
190bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    string s1 = line.substr(0, idx);
191bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    string s2 = line.substr(idx + 1);
192bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (s1 == "obj") {
193bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      Location location = {LT_OBJ, s2};
194bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      trace->locations.push_back(location);
195bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return true;
196bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    } else if (s1 == "fun") {
197bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      Location location = {LT_FUN, s2};
198db2b85ac6df2716e3ae85cccc29eefafa6b5d047Evgeniy Stepanov      // A suppression frame can only have ( or ) if it comes from Objective-C,
199db2b85ac6df2716e3ae85cccc29eefafa6b5d047Evgeniy Stepanov      // i.e. starts with +[ or -[ or =[
200db2b85ac6df2716e3ae85cccc29eefafa6b5d047Evgeniy Stepanov      PARSER_CHECK(s2.find_first_of("()") == string::npos ||
201db2b85ac6df2716e3ae85cccc29eefafa6b5d047Evgeniy Stepanov                   (s2[1] == '[' && strchr("+-=", s2[0]) != NULL),
202db2b85ac6df2716e3ae85cccc29eefafa6b5d047Evgeniy Stepanov                   "'fun:' lines can't contain '()'");
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // Check that we don't have template arguments in the suppression.
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // Caveat: don't be confused by "operator>>" and similar...
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        size_t checked_till = 0;
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // List of possible >>-like operators, sorted by the operation length.
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        const char *OP[] = {">>=", "<<=",
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            ">>", "<<",
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            ">=", "<=",
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            "->", "->*",
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            "<", ">"};
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        bool check_failed = false;
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        while (!check_failed && checked_till < s2.size()) {
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          size_t next = s2.find_first_of("<>", checked_till);
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          if (next == string::npos)
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          if (next < 8) {
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            // operatorX won't fit
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            check_failed = true;
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          }
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          for (size_t i = 0; i < TS_ARRAY_SIZE(OP); i++) {
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            size_t op_offset = ((string)OP[i]).find(s2[next]);
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (op_offset == string::npos)
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              continue;
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (next >= 8 + op_offset &&
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                "operator" == s2.substr(next- (8 + op_offset), 8) &&
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                OP[i] == s2.substr(next- op_offset, strlen(OP[i]))) {
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              checked_till = next + strlen(OP[i] + op_offset);
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              break;
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          }
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        }
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        PARSER_CHECK(!check_failed, "'fun:' lines can't contain '<' or '>' "
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     "except for operators");
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
243bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      trace->locations.push_back(location);
244bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return true;
245bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    } else {
246bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      SetError("bad stack trace line");
247bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return false;
248bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    }
249bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
250bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
251bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
252bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Checks if this line can not be parsed by Parser::NextStackTraceTemplate
253bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// and, therefore, is an extra information for the suppression.
254bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::IsExtraLine(string line) {
255bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line == "..." || line == "{" || line == "}")
256bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return false;
257bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line.size() < 4)
258bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return true;
259bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string prefix = line.substr(0, 4);
260bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return !(prefix == "obj:" || prefix == "fun:");
261bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
262bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
263bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::NextStackTraceTemplate(StackTraceTemplate* trace,
264bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    bool* last_stack_trace) {
265bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string line = NextLineSkipComments();
266bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line == "}") {  // No more stack traces in multi-trace syntax
267bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    *last_stack_trace = true;
268bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return false;
269bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
270bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
271bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line == "{") {  // A multi-trace syntax
272bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    line = NextLineSkipComments();
273bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  } else {
274bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    *last_stack_trace = true;
275bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
276bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
277bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (true) {
278bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (!ParseStackTraceLine(trace, line))
279bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return false;
280bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    line = NextLineSkipComments();
281bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (line == "}")
282bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      break;
283bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
284bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return true;
285bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
286bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
287bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Parser::NextSuppression(Suppression* supp) {
288bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string line;
289bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  line = NextLineSkipComments();
290bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (line.empty())
291bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return false;
292bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // Opening {
293bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(line == "{", "expected '{'");
294bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // Suppression name.
295bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  line = NextLineSkipComments();
296bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(!line.empty(), "expected suppression name");
297bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  supp->name = line;
298bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // tool[,tool]:warning_name.
299bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  line = NextLineSkipComments();
300bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  PARSER_CHECK(!line.empty(), "expected tool[, tool]:warning_name line");
301bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (!ParseSuppressionToolsLine(supp, line))
302bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return false;
303bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (0) {  // Not used currently. May still be needed later.
304bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    // A possible extra line.
305bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    line = NextLineSkipComments();
306bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (IsExtraLine(line))
307bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      supp->extra = line;
308bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    else
309bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      PutBackSkipComments(line);
310bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
311bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // Everything else.
312bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  bool done = false;
313bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (!done) {
314bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    StackTraceTemplate trace;
315bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (NextStackTraceTemplate(&trace, &done))
316bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      supp->templates.push_back(trace);
317bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (error_)
318bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return false;
319bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
320bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  // TODO(eugenis): Do we need to check for empty traces?
321bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return true;
322bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
323bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
324bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct Suppressions::SuppressionsRep {
325bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  vector<Suppression> suppressions;
326bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  string error_string_;
327bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  int error_line_no_;
328bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
329bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
330bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy StepanovSuppressions::Suppressions() : rep_(new SuppressionsRep) {}
331bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
332bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy StepanovSuppressions::~Suppressions() {
333bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  delete rep_;
334bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
335bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
336bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint Suppressions::ReadFromString(const string &str) {
337bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  int sizeBefore = rep_->suppressions.size();
338bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  Parser parser(str);
339bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  Suppression supp;
340bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (parser.NextSuppression(&supp)) {
341bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    rep_->suppressions.push_back(supp);
342bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
343bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  if (parser.GetError()) {
344bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    rep_->error_string_ = parser.GetErrorString();
345bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    rep_->error_line_no_ = parser.GetLineNo();
346bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    return -1;
347bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
348bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return rep_->suppressions.size() - sizeBefore;
349bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
350bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
351bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring Suppressions::GetErrorString() {
352bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return rep_->error_string_;
353bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
354bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
355bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint Suppressions::GetErrorLineNo() {
356bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return rep_->error_line_no_;
357bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
358bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
359bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct MatcherContext {
360bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  MatcherContext(
361bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      const vector<string>& function_names_mangled_,
362bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      const vector<string>& function_names_demangled_,
363bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      const vector<string>& object_names_) :
364bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      function_names_mangled(function_names_mangled_),
365bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      function_names_demangled(function_names_demangled_),
366bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      object_names(object_names_),
367bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      tmpl(NULL)
368bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  {}
369bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
370bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const vector<string>& function_names_mangled;
371bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const vector<string>& function_names_demangled;
372bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const vector<string>& object_names;
373bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  StackTraceTemplate* tmpl;
374bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov};
375bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
376bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic bool MatchStackTraceRecursive(MatcherContext ctx, int trace_index,
377bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    int tmpl_index) {
378bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const int trace_size = ctx.function_names_mangled.size();
379bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  const int tmpl_size = ctx.tmpl->locations.size();
380bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  while (trace_index < trace_size && tmpl_index < tmpl_size) {
381bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    Location& location = ctx.tmpl->locations[tmpl_index];
382bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (location.type == LT_STAR) {
383bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      ++tmpl_index;
384bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      while (trace_index < trace_size) {
385bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        if (MatchStackTraceRecursive(ctx, trace_index++, tmpl_index))
386bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov          return true;
387bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      }
388bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      return false;
389bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    } else {
390bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      bool match = false;
391bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      if (location.type == LT_OBJ) {
392bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        match = StringMatch(location.name, ctx.object_names[trace_index]);
393bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      } else {
394bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        CHECK(location.type == LT_FUN);
395bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        match =
396bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov          StringMatch(location.name, ctx.function_names_mangled[trace_index]) ||
397bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov          StringMatch(location.name, ctx.function_names_demangled[trace_index]);
398bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      }
399bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      if (match) {
400bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        ++trace_index;
401bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        ++tmpl_index;
402bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      } else {
403bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        return false;
404bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      }
405bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    }
406bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
407bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return tmpl_index == tmpl_size;
408bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
409bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov
410bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool Suppressions::StackTraceSuppressed(string tool_name, string warning_name,
411bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const vector<string>& function_names_mangled,
412bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const vector<string>& function_names_demangled,
413bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    const vector<string>& object_names,
414bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    string *name_of_suppression) {
415bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  MatcherContext ctx(function_names_mangled, function_names_demangled,
416bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      object_names);
417bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  for (vector<Suppression>::iterator it = rep_->suppressions.begin();
418bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov       it != rep_->suppressions.end(); ++it) {
419bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    if (it->warning_name != warning_name ||
420bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        it->tools.find(tool_name) == it->tools.end())
421bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      continue;
422bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    for (vector<StackTraceTemplate>::iterator it2 = it->templates.begin();
423bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov         it2 != it->templates.end(); ++it2) {
424bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      ctx.tmpl = &*it2;
425bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      bool result = MatchStackTraceRecursive(ctx, 0, 0);
426bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      if (result) {
427bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        *name_of_suppression = it->name;
428bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov        return true;
429bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov      }
430bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov    }
431bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  }
432bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov  return false;
433bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}
434