public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH] Use effective-target instead of -std options
       [not found] <20160826114243.GP20016@redhat.com>
@ 2016-08-26 12:23 ` Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2016-08-26 12:23 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1656 bytes --]

On 26/08/16 12:42 +0100, Jonathan Wakely wrote:
>This large patch replaces most of the remaining uses of -std in
>dg-options with { target c++11 } or { target c++14 } effective
>targets.
>
>The advantage of this is that we will now test most things with the
>default gnu++14 mode. Previously most tests for C++11 features were
>only ever tested using gnu++11. It's also now simple to test the
>entire library using gnu++17 (which would have caught the ambiguities
>caused by std::string_view sooner) or gnu++98 (to ensure we don't
>accidentally introduce C++14 features into code that is supposed to
>work with gnu++98).
>
>Most of the testsuite patches I've been committing recently have been
>to make this possible, and to ensure that there are no FAILs for any
>-std option, including -std=c++* options as well as -std=gnu++*.
>
>Cycling through all the -std options by default (as the g++.dg tests
>do) would take too long, so I'm not changing it to do that. Instead
>I'm going to set up a nightly job to test all of them. We should
>probably add a new makefile target that does it automatically, but for
>now you can use:
>
>make check RUNTESTFLAGS='--target_board=\"unix{-std=gnu++98,-std=gnu++11,-std=gnu++14,-std=gnu++17}\"'
>
>Tested x86_64-linux and powerpc64le-linux, over a period of several
>weeks, with every possible -std option.
>
>Committed to trunk.
>

The mail above didn't make it to the lists, because the patch was too
large (it was only 75kb, but once converted to base64 it goes over the
100kb limit).

The patch is very boring, but was committed as r239777 for those who
want to see it.

I've re-attached the python util I used.



[-- Attachment #2: symverck.py --]
[-- Type: text/plain, Size: 5099 bytes --]

#!/usr/bin/python

from __future__ import print_function
import sys
import fnmatch
import subprocess
import argparse

GLOB, DEMANGLED = 1, 2

def read_patterns(filename):
	"""Read a linker script into a dictionary.

	Returns { "VER_1": {N: ("foo*", T), N:("bar[ij]", T)} }
	where N is the line number of the pattern
	and T is a bitmask of the elements GLOB and DEMANGLED.
	"""
	with open(filename) as f:
		INIT, VERSION, EXTERN_CXX = range(3)
		patterns = {}
		filename = filename.split('/')[-1]
		state = INIT
		ver = None
		local = False
		for n, line in enumerate(f):
			# trim comments
			line = line.partition('#')[0].strip()
			# skip blank lines
			if not line:
				continue
			n += 1
			if state == INIT:
				if line[-1] != '{':
					raise ValueError("{0}:{1}: Invalid characters at global scope: {2}".format(filename, n, line))
				ver = line[0:-1].rstrip()
				state = VERSION
				local = False
				continue
			elif state == VERSION:
				if line == "global:":
					continue
				elif line == "local:":
					local = True
					continue
				if line == 'extern "C++"':
					state = EXTERN_CXX
					continue
				if line[0] == '}' and line[-1] == ';':
					state = INIT
					continue
			elif state == EXTERN_CXX:
				if line == '{':
					continue
				elif line == '};':
					state = VERSION
					continue

			if line[-1] != ';':
				# TODO allow trailing semi-colon to be omitted at end of node
				raise ValueError("{0}:{1}: Invalid pattern: {2}".format(filename, n, line))

			if local:
				continue

			pattern = line[0:-1]
			pattern_type = 0
			if state == EXTERN_CXX:
				pattern_type |= DEMANGLED
			if pattern[0] == '"' and pattern[-1] == '"':
				pattern = pattern[1:-1]
			else:
				pattern_type |= GLOB
			patterns.setdefault(ver, {})[n] = (pattern, pattern_type)

		if state != INIT:
			raise ValueError("{0}: incomplete node: {1}".format(filename, ver))

		return patterns

class Demangler:
	def __enter__(self):
		self.child = subprocess.Popen(['c++filt'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
		return self

	def __exit__(self, exc_type, exc_value, traceback):
		self.child.stdin.close()

	def __call__(self, mangled):
		"""Demangle a symbol name."""
		self.child.stdin.write((mangled+'\n').encode())
		self.child.stdin.flush()
		return self.child.stdout.readline().decode().rstrip('\n')

def find_matches(symbols, patterns, verbose, full, conflicts = False):
	"""For each symbol name find which patterns it matches.

	Return a list of symbols and the patterns they match.

	When the optional argument conflicts is True only match symbols
	that match patterns in more than one version.
	"""
	with Demangler() as demangle:
		res = []
		count = 0
		for symbol in symbols:
			demangled = demangle(symbol)

			matches = {}

			for v, ps in iter(patterns.items()):
				for n, (p, t) in iter(ps.items()):
					if t & DEMANGLED:
						s = demangled
					else:
						s = symbol
					# Python fnmatch uses [!abc] not [^abc]
					p = p.replace('[^', '[!')
					if fnmatch.fnmatch(s, p):
						matches.setdefault(v, []).append(n)
						if not full:
							break

			if symbol == demangled:
				demangled = None

			if conflicts:
				if len(matches) > 1:
					res.append( (symbol, demangled, matches) )
					if verbose:
						sys.stdout.write('!')
						sys.stdout.flush()
			else:
				res.append( (symbol, demangled, matches) )

			if verbose:
				count += 1
				if not (count % 10):
					sys.stdout.write('#')
					sys.stdout.flush()
		if verbose:
			sys.stdout.write('\n')

		return res


def show_matches(all_matches, patterns, conflicts):
	for symbol, demangled, matches in all_matches:
		if len(matches) == 0:
			continue
		if conflicts:
			print("Symbol matches more than one version:")
		else:
			print("Symbol matches:")
		print(symbol)
		if demangled:
			print(demangled)
		for v, ms in iter(matches.items()):
			for m in ms:
				p = patterns[v][m][0]
				print("  {0:<18} {1} (line {2})".format(v, p, m))
		else:
			print('')

def main():
	parser = argparse.ArgumentParser(description='Read symbols from standard input and match against patterns in a linker script.')
	parser.add_argument('script', metavar='linker-script', help='linker version script')
	parser.add_argument('-c', '--conflicts', action = 'store_true', help='check for symbols that match multiple patterns')
	parser.add_argument('-u', '--unmatched', action = 'store_true', help='check for symbols that match no patterns')
	parser.add_argument('-f', '--full', action = 'store_true', help='check all patterns for a version (default: only report first match per version)')
	parser.add_argument('-v', '--verbose', action = 'store_true', help='show progress indicator every ten symbols processed')

	args = parser.parse_args()

	patterns = read_patterns(args.script)
	symbols = [line.strip() for line in sys.stdin]
	matches = find_matches(symbols, patterns, args.verbose, args.full and not args.unmatched, args.conflicts)

	if args.unmatched:
		for symbol in [s for s, _, m in matches if len(m) == 0]:
			print(symbol)
	else:
		show_matches(matches, patterns, args.conflicts)

if __name__ == "__main__": main()

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-08-26 12:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20160826114243.GP20016@redhat.com>
2016-08-26 12:23 ` [PATCH] Use effective-target instead of -std options Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).